三子棋小游戏
今天接触到了小时候经常玩的一个游戏——三子棋,实现的过程中有好多东西自己根本想不到,或许是代码量太少,经验不够吧,反正觉得挺不容易的。下面放上我的代码以及思路。
1.游戏中定义的一些函数及变量的说明
char ret = 0;//定义一个接收判断谁赢的返回字符变量
char board[3][3] = { 0 };//用二维数组定义表示棋盘
void Menu();//菜单
void Game();//游戏
void InitBoard(char board[][3], int row, int col);//初始化棋盘
void ShowBoard(char board[][3], int row, int col);//显示棋盘
void PlayerMove(char board[][3], int row, int col);//玩家操作
void ComputerMove(char board[][3], int row, int col);//电脑操作
char IsWin(char board[][3], int row, int col);//判断输赢
static int full(char board[][3], int row, int col)//判断棋盘是否放满
ret接收的返回值有四种分别是 空格,大写字母X,大写字母O和P,ret为X则证明玩家获胜,是O则电脑胜利,P则表示平局。
row和col为接收棋盘大小的两个形参。
2.首先定义一个Menu界面~
void Menu()
{
printf("\t\t\t\t\t**************************\n");
printf("\t\t\t\t\t**************************\n");
printf("\t\t\t\t\t*********1.开始***********\n");
printf("\t\t\t\t\t*********0.退出***********\n");
printf("\t\t\t\t\t**************************\n");
printf("\t\t\t\t\t**************************\n");
}
它的样子是这样的,很low但是现阶段我满足了,哈哈哈!
3.然后我们定义一个Game(),代码如下
void Game()
{
char ret = 0;//定义一个接收判断谁赢的返回字符
char board[3][3] = { 0 };//用二维数组定义表示棋盘
InitBoard(board, 3, 3);//初始化棋盘,让棋盘为空
ShowBoard(board, 3, 3);//显示棋盘
while (1)//
{
PlayerMove(board, 3, 3);
ShowBoard(board, 3, 3);
ret = IsWin(board, 3, 3);
if (ret != ' ')
{
break;
}
ComputerMove(board, 3, 3);
ShowBoard(board, 3, 3);
ret = IsWin(board, 3, 3);
if (ret != ' ')
{
break;
}
}
if (ret == 'X')
{
printf("玩家获胜\n");
}
if (ret == 'O')
{
printf("电脑获胜\n");
}
if (ret == 'P')
{
printf("平局\n");
}
}
每次玩家和电脑进行操作后都要对ret的值进行判断,ret不是空格则游戏结束,跳出while循环判断结果并进行输出。
4.棋盘初始化和显示棋盘
棋盘初始化
void InitBoard(char board[][3], int row, int col)
{
memset(board, ' ', row*col*sizeof(char));//游戏开始给棋盘的每个空间都置为空
}
memset是一个内存清零的函数它的头文件是#include<string.h>
使用方法:memset(void s, int ch, size_t n);
这里s表示的是你想要给谁内存清零,ch表示你想把他变成什么,size就很明显是说想要改变多少内存里的东西。
显示棋盘
棋盘的样子
void ShowBoard(char board[][3], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)//控制行
{
for (j = 0; j < col; j++)//控制列
{
printf(" %c ", board[i][j]);//打印字符二维数组中存储的符号
if (j < col - 1)//只需要打两列,所以为col-1,满足条件打印|
{
printf("|");
}
}
putchar('\n');//每一行打完后使用putchar进行换行
if (i < row - 1)//同理对每行的分隔符进行打印
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
putchar('\n');
}
}
}
定义两个变量i和j来控制打印棋盘,i控制行,j控制列。
通过观察棋盘样子我们发现只需要打两个竖行和横行,由于是从0开始,所以控制当i和j分别小于row-1和col-1时进行打印棋盘格子。
5.玩家操作和电脑操作
玩家操作
void PlayerMove(char board[][3], int row, int col)
{
int x = 0;//定义变量X和Y,玩家输入坐标
int y = 0;
while (1)
{
printf("请输入你的落子位置(1-3):");//因为棋盘是3*3大小所以是1-3
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] = 'X';
break;
}
else//当该位置不为空,提示重新输入
{
printf("此位置已被占用,请重新输入。\n");
}
}
else//不满足棋盘条件,提示输入不合理
{
printf("您输入的位置不合理。\n");
}
}
}
我们知道在数组中数组下标是从0开始的,可是现实感官中通常从1开始,所以在对每一格进行赋值是需要i-1和j-1.
电脑操作
电脑操作是随机获取一个空位置进行下棋
void ComputerMove(char board[][3], int row, int col)
{
int i=0, j=0;
printf("电脑的选择:\n\n");
while (1)
{
i = rand() % 3 + 1;//获取随机数i和j
j = rand() % 3 + 1;
if (board[i][j] == ' ')//当该位置为空,下棋
{
board[i][j] = 'O';
break;
}
}
}
6.判断输赢
在这里我定义了一个返回值为char类型的函数,输出输赢在Game()中进行。
当每一行,每一列或每一斜行都为相同字符且不为空时返回这个字符。
当棋盘满的时候还没有出现当每一行,每一列或每一斜行都为相同字符时返回P
char IsWin(char board[][3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//行
if (board[i][0] == board[i][1]&& board[i][1] == board[i][2]&& board[i][0] != ' ')
{
return board[i][0];
}
//列
if (board[0][i] == board[1][i] && board[1][i] == board[2][i]&& board[0][i] != ' ')
{
return board[0][i];
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2]&& board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0]&& board[0][0] != ' ')
{
return board[0][2];
}
//平局
if (full(board, row, col) == 1)
{
return 'P';
}
}
//没有赢也没有平局
return ' ';
}
判断棋盘是否放满
对棋盘进行遍历,若还有位置为空则为放满,返回0,棋盘放满则返回1
static int full(char board[][3], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
7.主函数
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//设置随机种子,使每次游戏时电脑操作不和上次游戏完全相同
do{
Menu();
printf("请输入你的选择:");
scanf("%d", &input);
switch (input)
{
case 1:
Game();
break;
case 0:
printf("游戏结束!\n");
break;
default:
printf("您的选择有误!\n\n");
break;
}
} while (input);
return 0;
}
到这里我的三子棋小游戏也就完全结束了,在写这个游戏中我学会了如何对二维数组进行遍历,加强了我对循环的使用,最后放一波完整的游戏截图吧!