大家好呀,我是心跳sy,今天给大家带来一个简单好玩的c语言小游戏——三子棋(多子棋),三子棋是一个可以对c语言基础知识进行系统复习回顾的小项目,建议初学c语言的宝子们都一定要自己多多尝试哦,今天给大家分享一下我实现的三子棋项目,有任何问题欢迎各位大佬指正支持哦~~嘻嘻。
首先三子棋或者多子棋是一个n*n的棋盘,所以我们在写之前会联想到二维数组的构建,通过二维数组,确定棋盘的行和列,进而确定一系列函数,对二维数组进行初始化赋值、判断输赢、进行下棋、显示输出等功能,进而实现三子棋或者多子棋的构建。
实现这个项目我们可以分三个文件进行,分别是test.c、game.c、game.h这三个文件,可以使我们的项目更加清楚明了,也可以更好地控制整个程序的运行。其中test.c文件中存放代码主体框架部分;game.c文件主要实现游戏地运行过程,包含有关游戏过程实现的所有函数定义;game.h包含宏定义行列、需要用到的库函数头文件以及各个函数的声明。下面代码按照分文件分模块进行实现:
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏!\n");
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
首先在主函数中srand((unsigned int)time(NULL))初始了随机函数种子 ,我们这里取时间作为随机种子,由于时间是不断变化的,所以可以产生不同的随机值,之后我们电脑下棋随机值的部署就是通过随机值生成器srand()生成时间种子再用rand()产生一个随机数。这里的unsigned int 是强制转换类型,意为将参数种子强制转换为无符号整型,通常我们用time(NULL)的返回值作为种子,来初始化rand()的起始值。
首先我们需要再循环之前就执行一次要不要进行游戏等一系列选择,所以我们采用do....while()循环,首先打印一个菜单menu(),对是否进行游戏进行选择,这里我们用scanf输入一个整数进行选择,用switch分支语句进行具体选择,若传入值为1则开始游戏,进入game()函数中,若为0则退出游戏,传入其他数值则重新进入循环选择。
首先定义一个字符型二维数组board,其中行和列由头文件中宏替换进行定义,这里我初始化行和列为3,我们同样也可改为5、10等等。
#define ROW 3
#define COL 3
开始将二维数组各个元素初始为空格
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;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
//先打印数据
printf(" %c ", board[i][j]);//注意为使数据居于中间,需在%c两边加空格
if (j
初始化打印的表格如下:(此为3*3的表格,若需修改为10*10则只需修改头文件中宏定义中的列和行)
这里的board[x - 1][y - 1],因为玩家输入的坐标不会像程序员们一样按照数组下标从0开始的规则,而是肉眼可见的行和列,于是电脑在判断时需要将x,y坐标各减一。
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋:\n");
while (1)
{
printf("请输入下棋坐标(中间用空格分开)如(1 1)\n");
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] = '*';//将'*'作为玩家下的棋
break;
}
else
printf("坐标被占用,请重新输入\n");
}
else
{
printf("输入坐标非法,请重新输入!\n");
}
}
}
这里的x = rand() % row意为给x随机取一个0~row-1之间的随机整数,如x=rand()%3就是对3取余数,所得的x值就为0~2之间的随机整数,对y同理。
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;//产生随机值
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
此部分代码对游戏实现非常重要,我们需要分别判断行列,以及主对角线、副对角线元素是否相等,从而判定谁赢谁输,这里我们采用for循环以及if语句嵌套的方式进行判断,可以对任意设定的行和列数进行判断。我们规定:
玩家赢 --- 返回'*'
电脑赢 --- 返回'#'
平局 --- 返回'Q'
游戏继续- 返回'C'
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int n = 0;
for (i = 0; i < row; i++)
{
int j = 0;//计数器
int r = 0;
for (n = 0; n < col; n++)
{
if (board[i][n] == '*')
{
j++;
}
if (board[i][n] == '#')
{
r++;
}
}
if (j == row)
{
return '*';
}
if (r == row)
{
return '#';
}
}
for (i = 0; i < row; i++)
{
//清零
int r = 0;
int j = 0;
for (n = 0; n < col; n++)
{
if (board[n][i] == '*')
{
r++;
}
if (board[n][i] == '#')
{
j++;
}
}
if (r == col)
{
return '*';
}
if (j == col)
{
return '#';
}
}
//判断正对角线
int r = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (n = 0; n < col; n++)
{
if (i == n)
{
if (board[i][n] == '*')
{
r++;
}
if (board[i][n] == '#')
{
j++;
}
}
}
}
if (r == row)
{
return '*';
}
if (j == row)
{
return '#';
}
//判断反对角线
r = 0;
j = 0;
for (i = 0; i < row; i++)
{
if (board[i][row - 1 - i] == '*')
{
r++;
}
if (board[i][row - 1 - i] == '#')
{
j++;
}
}
if (r == row)
{
return '*';
}
if (j == row)
{
return '#';
}
//判断平局
if (IsFull(board, row, col))
{
return 'Q';
}
return 'C';
}
此函数嵌套在IsWin()函数中最后一个if语句的判断条件中,用来判断是否为平局,若return 1则进入if语句中,返回“平局”。
static 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;//如果遍历完整个二维数组没有空格,返回1
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("**************************************\n");
printf("**********请选择是否玩游戏:**********\n");
printf("*************1.开始游戏***************\n");
printf("*************0.退出游戏***************\n");
printf("**************************************\n");
}
void game()
{
char board[ROW][COL];
int ret = 0;
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ret= IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏!\n");
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
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;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("坐标被占用,请重新输入\n");
}
else
{
printf("输入坐标非法,请重新输入!\n");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
static 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;
}
//玩家赢 - '*'
//电脑赢 - '#'
//平局 --- 'Q'
//游戏继续-'C'
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int n = 0;
for (i = 0; i < row; i++)
{
int j = 0;//计数器
int r = 0;
for (n = 0; n < col; n++)
{
if (board[i][n] == '*')
{
j++;
}
if (board[i][n] == '#')
{
r++;
}
}
if (j == row)
{
return '*';
}
if (r == row)
{
return '#';
}
}
for (i = 0; i < row; i++)
{
//清零
int r = 0;
int j = 0;
for (n = 0; n < col; n++)
{
if (board[n][i] == '*')
{
r++;
}
if (board[n][i] == '#')
{
j++;
}
}
if (r == col)
{
return '*';
}
if (j == col)
{
return '#';
}
}
//判断正对角线
int r = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (n = 0; n < col; n++)
{
if (i == n)
{
if (board[i][n] == '*')
{
r++;
}
if (board[i][n] == '#')
{
j++;
}
}
}
}
if (r == row)
{
return '*';
}
if (j == row)
{
return '#';
}
//判断反对角线
r = 0;
j = 0;
for (i = 0; i < row; i++)
{
if (board[i][row - 1 - i] == '*')
{
r++;
}
if (board[i][row - 1 - i] == '#')
{
j++;
}
}
if (r == row)
{
return '*';
}
if (j == row)
{
return '#';
}
//判断平局
if (IsFull(board, row, col))
{
return 'Q';
}
return 'C';
}
#pragma once
#include
#include
#define ROW 10
#define COL 10
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);
char IsWin(char board[ROW][COL], int row, int col);
谢谢大家!感谢各位大佬们的阅读!本人编程小白一只,如有错误问题,欢迎友友们在评论区留言,欢迎各位大佬友友们指正哦!!!