写在前面的废话
先用这个号写C吧。后面的机器学习的资料如果开学后能坚持下去,会码在这个号上的。相信小尚一定能坚持下去!!^_^
相对于五子棋,对我这个“被C语言抛弃”3年的女码农,三子棋比较容易上手和想通,虽然调试也调了一下午,没办法,谁让我总犯一些低级错误呢。不过好歹是能运行了,可能还有一些小错误,后面的话会不断修改和完善的。
三子棋:首先由玩家下棋(选坐标),选定坐标后,电脑进行选择,玩家棋子为“*”,电脑棋子为“#”最终谁先连成一线获胜,若棋盘满后双方无一人连成一线则为平局。
整体游戏的主函数分为两个模块。打印菜单模块和玩游戏模块。分别用menu() 函数和game()函数表示。
其中为了实现游戏功能,在game()函数中还需包含以下几个功能:
1. 对棋盘进行初始化并打印: InitBoard()函数对棋盘进行初始化,通俗的来讲就是讲棋盘上的每一个点置为空格。DisplayBoard()是打印数据和分割行。`
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
//打印数据
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");//
}
printf("\n");
//打印分割行
if(i<row-1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
2.playerMove()函数实现玩家下棋过程
使用这个函数主要思想是,在棋盘内找一个点打印‘*’,其中这个点不能是已经有过棋子的点,另外此点不能超过棋盘范围。
void playerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家走:>");
printf("请输入坐标:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
}
else
{
printf("该坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,请重新输入:\n");
}
}
需要注意的是这里是用数组存储的落子点,所以在棋盘中我们看到的3并不是数组下标中的3(因为数组下标从0开始,我们下棋的时候没有0位),所以在数组中要实行-1操作。
3. computerMove()函数实现电脑下棋功能,电脑落子点为随机数,我们使用了系统函数来选取随机数,srand((unsigned int )time(NULL))语句,要记得包含头文件哦。%row和col是为了使随机数落在0-3也就是棋盘之间。
void computerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:>\n");
int x = rand() % row;
int y= rand() % col;
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
4.IsWin()函数来实现判断两者的输赢,在这里使用了一个比较傻的程序,就是简单的判断每行每列和对角线上的元素是否有三个连续相同的子。若有则返回最后一个点的值方便主函数进行判断,若返回值为‘*’则玩家赢,若返回值为‘#’则电脑赢。但当每行每列和对角线上的元素都不相同且棋盘无子可落,则返回F,提示棋盘已满。为平局。判断棋盘是否已满的函数为isfull()函数。通过搜索是否有空格“ ”来判断目前棋盘的情况。
int IsWin(char board[][ROW], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ')
{
return board[2][i];
}
else if (board[i][2] == board[i][1] && board[i][1] == board[i][0] && board[i][0] != ' ')
{
return board[i][0];
}
else if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
{
return board[2][0];
}
if (isfull(board, ROW, COL)==1)
return 'F';
else
return ' ';
}
}
int isfull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
另外在game()函数中,玩家进行游戏后,只需判断返回值是否含有“*”或“F”,不用判断电脑是否会赢,我下午人傻,这个点没有想到。另外,我还定义了一个头文件,命名为game.h
# include
#include
#include
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void playerMove(char board[ROW][COL], int row, int col);
void computerMove(char board[ROW][COL], int row, int col);
int IsWin(char board[][ROW], int row, int col);
最后对game()函数做总结。
Iswin()函数下面应该包含一个isfull()函数,图内没有体现。
最后是主函数:
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");
}
} while (input);
return 0;
}
以我的粗心程度,我觉得肯定会有错误,哈哈哈哈。随后我会不断补充新的程序进行改进。
小废话:我在想著名的阿法狗是不是通过人和其进行训练多次后,或者是自己和自己进行训练决策,形成一个个神经网络。当与选手对决时,对所有落棋点进行计算,并进行预判,并对预判结果进行统计分析,决策出一个最优的落棋点,如果是这样的话,那也不是不可能啊。毕竟计算量已经不是目前最主要的限制因素了。(我瞎想的,嘿嘿嘿)