使用工具:Visual Studio 2022
一、游戏主循环
游戏主循环使用do…while就可以在循环中判定是否跳出循环以及继续下一把游戏,所以非常合适做游戏的主循环。大致框架如下:
int input;
do {
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
break;
case 0:
break;
default:
break;
}
} while (input);
接着,开始增加一些细节,确定这个主循环是否能够成功运行起来。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int input;
//主循环
do {
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("游戏开始!\n");
break;
case 0:
printf("成功退出游戏!\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}
二、设计菜单
一个游戏应该要包含有一个菜单来指引玩家。
三、初始化游戏
(1)新建.c文件和.h头文件
游戏应该要先完成初始化,玩家再进行操作,这样子才是一个合理的步骤。考虑到需要通过函数的使用来实现这些功能,因此需要新建一个.c文件和.h的头文件,在头文件上上面声明,在.c文件里面实现代码功能。
之后进行头文件的引用(如下图所示), 可以把使用的库函数移到头函数当中。
(2)写入初始化相关的函数
当选择进入游戏的时候开始执行相关函数来完成游戏的初始化。
1)初始化字符数组
因为要先初始化一个数组,用于储存棋盘上的棋子,所以我们需要向函数中传参,传入一个二维数组的首地址(如图中所示),这样才能在接下来的过程中使用。
把棋盘初始化为看不见的空格。
//初始化棋盘
void InitBoard(char board[3][3])
{
int i = 0, j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
board[i][j] = ' ';
}
}
}
2)打印棋盘
再写一个函数用来实时打印棋盘的情况。
//打印棋盘
void PrintBoard(char board[3][3])
{
int i = 0, j = 0;
for (i = 0; i < 3; i++)
{
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i < 2)
printf("---|---|---\n");
}
}
运行查看效果如下:
四、下棋
在下棋的时候是一方下一次,因此在游戏的部分中需要加入循环语句。
//游戏
void Game()
{
char Board[3][3];
//初始化代码
InitBoard(Board);
PrintBoard(Board);
while(1)
{
//玩家下棋
PlayerPlay(Board);
//电脑下棋
ComputerPlay(Board);
}
}
(1)玩家下棋
玩家下棋通过输入相应的坐标来实现。不过,在操作数组的时候得减一。
//玩家下棋
void PlayerPlay(char board[3][3])
{
printf("玩家下棋!\n");
while (1)
{
int x = 0, y = 0;
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
//判断该位置是否有棋子以及输入的坐标是否合理
if (x >= 1 && x <= 3 & y >= 1 && y <= 3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '#';
break;
}
else
printf("该位置已有棋子,请下在别处!\n");
}
else
printf("非法坐标,请重新输入!\n");
}
}
(2)电脑下棋
在玩家下棋的功能实现的基础上,给与电脑下棋一个随机数字生成器,这样就能做出最简单的人机。
//电脑下棋
void ComputerPlay(char board[3][3])
{
printf("电脑下棋!\n");
while (1)
{
int x = rand() % 3 + 1;
int y = rand() % 3 + 1;
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
}
}
五、判断输赢
再判断输赢的时候有大致四种情况,一个玩家赢,一个电脑赢,还有一个平局和一个继续下棋。这四种情况分别设置一个返回值,返回一个字符,这样就可以判断是哪一种情况。
//判断输赢
char IsWin(char board[3][3])
{
//行
//return F
//列
//return F
//对角线
//return F
//平局
//return 'P';
//继续
//return 'C';
}
先写判断棋盘某行是否已经满足获胜条件。
//行
int i = 0;
for (i = 0; i < 3; i++)
{
if (board[i][1] == board[i][0] && board[i][1] == board[i][2] && board[i][1] != ' ')
return board[i][1];
}
之后我们就可以从中已写好的代码中扩展到其他获胜条件。
//列
int j = 0;
for (j = 0; j < 3; j++)
{
if (board[1][j] == board[0][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
return board[1][j];
}
//对角线
if (board[1][1] == board[0][0] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
if (board[1][1] == board[0][2] && board[1][1] == board[2][0] && board[1][1] != ' ')
return board[1][1];
//平局
//return 'P';
//继续
//return 'C';
if (IsNull(board))
return 'P';
else
return 'C';
最后写判断棋盘是否被下满的函数,这样子可以判断是否平局以及棋盘被下满了。
//是否下满棋盘
int IsNull(char board[3][3])
{
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
六、完善细节
最后完善亿点点的细节这个游戏就做完了。
七、完整代码
头文件 game.h
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//初始化棋盘
void InitBoard(char board[3][3]);
//打印棋盘
void PrintBoard(char board[3][3]);
//玩家下棋
void PlayerPlay(char board[3][3]);
//电脑下棋
void ComputerPlay(char board[3][3]);
//是否下满棋盘
int IsNull(char board[3][3]);
//判断输赢
char IsWin(char board[3][3]);
.c文件 game.c
#include"game.h"
//初始化棋盘
void InitBoard(char board[3][3])
{
int i = 0, j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void PrintBoard(char board[3][3])
{
int i = 0, j = 0;
for (i = 0; i < 3; i++)
{
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i < 2)
printf("---|---|---\n");
}
}
//玩家下棋
void PlayerPlay(char board[3][3])
{
printf("玩家下棋!\n");
while (1)
{
int x = 0, y = 0;
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
//判断该位置是否有棋子以及输入的坐标是否合理
if (x >= 1 && x <= 3 & y >= 1 && y <= 3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '#';
break;
}
else
printf("该位置已有棋子,请下在别处!\n");
}
else
printf("非法坐标,请重新输入!\n");
}
}
//电脑下棋
void ComputerPlay(char board[3][3])
{
printf("电脑下棋!\n");
while (1)
{
int x = rand() % 3 + 1;
int y = rand() % 3 + 1;
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
}
}
//是否下满棋盘
int IsNull(char board[3][3])
{
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
//判断输赢
char IsWin(char board[3][3])
{
//行
int i = 0;
for (i = 0; i < 3; i++)
{
if (board[i][1] == board[i][0] && board[i][1] == board[i][2] && board[i][1] != ' ')
return board[i][1];
}
//列
int j = 0;
for (j = 0; j < 3; j++)
{
if (board[1][j] == board[0][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
return board[1][j];
}
//对角线
if (board[1][1] == board[0][0] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
if (board[1][1] == board[0][2] && board[1][1] == board[2][0] && board[1][1] != ' ')
return board[1][1];
//平局
//return 'P';
//继续
//return 'C';
if (IsNull(board))
return 'P';
else
return 'C';
}
.c文件 main.c
#include"game.h"
//菜单
void Menu()
{
printf("----------------------------------\n");
printf("------------1.开始游戏------------\n");
printf("------------0.退出游戏------------\n");
printf("----------------------------------\n");
}
//游戏
void Game()
{
char ret;
char Board[3][3];
//初始化代码
InitBoard(Board);
PrintBoard(Board);
while(1)
{
//玩家下棋
PlayerPlay(Board);
PrintBoard(Board);
//判断输赢
ret = IsWin(Board);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerPlay(Board);
PrintBoard(Board);
//判断输赢
ret = IsWin(Board);
ret = IsWin(Board);
if (ret != 'C')
{
break;
}
}
//打印结果
if (ret == '#')
{
printf("玩家获胜!\n");
}
if (ret == '*')
{
printf("电脑获胜!\n");
}
if (ret == 'P')
{
printf("平局!\n");
}
}
int main()
{
srand((unsigned int)time(NULL));
int input;
//主循环
do {
Menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
Game();
break;
case 0:
printf("成功退出游戏!\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}