基于MFC实现五子棋存盘读盘
时间: 2023-09-13 09:12:49 浏览: 174
以下是基于MFC的五子棋存盘读盘实现:
1. 创建MFC工程,将以下代码添加到stdafx.h文件中:
```cpp
#include <fstream>
using namespace std;
#define BLACK 1
#define WHITE 2
const int MAX_LINE = 15;
class Chessboard {
private:
int board[MAX_LINE][MAX_LINE] = { 0 }; // 棋盘,0表示无棋子,1表示黑棋,2表示白棋
int turn = BLACK; // 轮到哪一方下棋,1表示黑棋,2表示白棋
int winner = 0; // 获胜方,0表示未分胜负,1表示黑棋获胜,2表示白棋获胜
public:
Chessboard() {}
// 判断是否越界
bool checkBound(int x, int y) {
return x >= 0 && x < MAX_LINE && y >= 0 && y < MAX_LINE;
}
// 判断是否可以下棋
bool isLegal(int x, int y) {
return checkBound(x, y) && board[x][y] == 0;
}
// 下棋
bool putChess(int x, int y) {
if (!isLegal(x, y)) return false;
board[x][y] = turn;
turn = 3 - turn; // 切换到对方下棋
return true;
}
// 判断是否有五子连珠
bool checkWinner(int x, int y) {
int dx[4] = { 1, 1, 0, -1 };
int dy[4] = { 0, 1, 1, 1 };
int cnt;
for (int k = 0; k < 4; k++) {
cnt = 1;
for (int i = x + dx[k], j = y + dy[k]; checkBound(i, j) && board[i][j] == board[x][y]; i += dx[k], j += dy[k]) {
cnt++;
}
for (int i = x - dx[k], j = y - dy[k]; checkBound(i, j) && board[i][j] == board[x][y]; i -= dx[k], j -= dy[k]) {
cnt++;
}
if (cnt >= 5) {
winner = board[x][y];
return true;
}
}
return false;
}
// 打印棋盘
void printBoard(CDC* pDC) {
pDC->TextOut(20, 20, " ");
for (int i = 0; i < MAX_LINE; i++) {
CString str;
str.Format("%d ", i);
pDC->TextOut(20 + i * 20, 20, str);
}
for (int i = 0; i < MAX_LINE; i++) {
CString str;
str.Format("%d ", i);
pDC->TextOut(20, 40 + i * 20, str);
for (int j = 0; j < MAX_LINE; j++) {
if (board[i][j] == 0) pDC->TextOut(20 + j * 20, 40 + i * 20, "+ ");
else if (board[i][j] == BLACK) pDC->TextOut(20 + j * 20, 40 + i * 20, "X ");
else pDC->TextOut(20 + j * 20, 40 + i * 20, "O ");
}
}
}
// 存盘
void saveGame(const char* filename) {
ofstream fout(filename);
fout << turn << endl;
fout << winner << endl;
for (int i = 0; i < MAX_LINE; i++) {
for (int j = 0; j < MAX_LINE; j++) {
fout << board[i][j] << " ";
}
fout << endl;
}
fout.close();
}
// 读盘
bool loadGame(const char* filename) {
ifstream fin(filename);
if (!fin) return false;
fin >> turn >> winner;
for (int i = 0; i < MAX_LINE; i++) {
for (int j = 0; j < MAX_LINE; j++) {
fin >> board[i][j];
}
}
fin.close();
return true;
}
};
```
2. 在对话框上添加一个按钮和一个编辑框,按钮用于存盘,编辑框用于输入/显示文件名。
3. 在按钮的点击事件中添加以下代码:
```cpp
void CMyDlg::OnBnClickedButtonSave()
{
CString filename;
m_editFileName.GetWindowText(filename);
if (filename.IsEmpty()) {
AfxMessageBox("请输入文件名!");
return;
}
Chessboard chessboard;
chessboard.saveGame(filename);
AfxMessageBox("存盘成功!");
}
```
4. 在对话框的OnInitDialog函数中添加以下代码:
```cpp
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_FILENAME, m_editFileName);
}
BOOL CMyDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 在此添加额外的初始化
m_editFileName.SetWindowText("game.txt");
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
```
5. 在对话框上添加一个菜单项,用于读盘,添加以下代码:
```cpp
void CMyDlg::OnFileLoad()
{
CString filename;
m_editFileName.GetWindowText(filename);
if (filename.IsEmpty()) {
AfxMessageBox("请输入文件名!");
return;
}
Chessboard chessboard;
if (chessboard.loadGame(filename)) {
m_chessboard = chessboard;
m_chessboard.printBoard(GetDC());
AfxMessageBox("读盘成功!");
}
else {
AfxMessageBox("读盘失败!");
}
}
```
6. 在资源文件中添加菜单项,并在消息映射中添加以下代码:
```cpp
BEGIN_MESSAGE_MAP(CMyDlg, CDialogEx)
ON_COMMAND(ID_FILE_LOAD, &CMyDlg::OnFileLoad)
END_MESSAGE_MAP()
```
7. 在对话框类中添加一个私有成员变量m_chessboard,用于存储当前的棋盘状态。
```cpp
class CMyDlg : public CDialogEx
{
private:
Chessboard m_chessboard;
// ...
};
```
8. 在对话框的OnPaint函数中添加以下代码:
```cpp
void CMyDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CDialogEx::OnPaint()
m_chessboard.printBoard(&dc);
}
```
9. 编译并运行程序,点击存盘按钮可以将当前的棋盘状态存储到文件中,点击读盘菜单项可以从文件中读取之前存储的棋盘状态。
阅读全文