三子棋相信大家基本都玩过,也可以称作一条龙、井字棋、圈圈叉叉、九宫棋等等,今天我们来用c语言实现三子棋,此游戏主要练习大家应对偏多代码时函数的使用,创作不易,还请各位小伙伴多多关注,以后也会更新各种小游戏还有关于c语言的博客。
三子棋(介绍)
游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。 🌞
实现效果
🧐首先开始执行程序,一张菜单,可以选择0或者1,0退出,1进入游戏
如果选择1的话,开始游戏,根据坐标填入数字,直到棋盘满了或者一方先连成一条线获胜为止。
代码实现
1.打印菜单
void menu() //菜单
{
printf("****************************\n");
printf("****** 1. play *****\n");
printf("****** 0. exit *****\n");
printf("****************************\n");
}
菜单必不可少,让用户进来了解怎么操作
2.main函数
int main()
{
int input = 0;
srand((unsigned)time(NULL)); //生成随机数用于人机自动落子
do
{
menu(); //do-while语句进来先打印菜单栏
printf("请进行选择(0/1)\n"); //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了
scanf("%d", &input);
switch (input) //switch语句进行选择,一目了然
{
case 1:
game(); //进入游戏
break;
case 0:
printf("成功退出");
break;
default:
printf("输入错误,请重新输入");
break;
}
} while (input); //为0中止
}
由于进程序就有菜单弹出所以这里选择do。while语句,再用switch语句进行判断,当玩家输入1,进入游戏,当玩家输入0,退出程序
- 让我们想想进入游戏后都需要些什么(也就是game()函数都需要什么)❔
- 首先我们需要一张棋盘,棋盘本质上来说是一个3*3的空间,我们这里选择用二维数组来放下。
char board[ROW][COL] = { 0 };
3.初始化棋盘
- 在刚进游戏的时候,棋盘上是空的,所以我们要把棋盘上所有位置都初始化成空格。
void InitBoard(char board[ROW][COL],int row,int col) //形参的名字不能和define定义的相同,不然会报错
{
for (int i = 0; i < row; i++) //把棋盘初始化为空格
{
for(int j=0;j< col;j++)
{
board[i][j] =' ';
}
}
//也可以使用库函数memset
//memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}
4.打印棋盘
- 初始化棋盘之后我们就可以开始打印了
void printboard(char board[ROW][COL],int row,int col)//~用于打印棋盘
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++) //打印一行
{
printf(" %c ", board[i][j]);
if (j<col - 1) //打印col-1个|,做到 棋子|棋子|棋子
{
printf("|");
}
}
printf("\n");
if (i < row - 1) //打印分割线---|---|---
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < COL - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
✨✨如果游戏开始只有棋子,那么玩家看到的是一片空,所以我们要打印一个棋盘出来,这里选择用ROW(行)和COL(列)来控制棋盘的长短,如果想打印更大的棋盘就只需改掉define定义的ROW和COL即可。
5.玩家落子
- 打印完棋盘之后玩家进行落子
void playerMove(char board[ROW][COL], int row, int col)//~玩家下子
{
printf("该你了,请选择坐标(?,?)\n");
while (1)
{
int num1=0; //玩家输入的行
int num2=0; //玩家输入的列
scanf("%d,%d", &num1, &num2);
if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0)) //如果超出棋盘范围,结束本次循环重新选择
{
printf("请输入正确位置");
continue;
}
if (board[num1-1][num2-1] == ' ')
{
board[num1-1][num2-1] = '*'; //返回1 ,落子成功,跳出循环
break;
}
else
{
printf("请选择空位下子\n"); //返回0 落子失败,重新输入
}
}
}
✨✨轮到玩家输入,首先要给个提示,提示玩家落子,如果玩家输入的坐标不对的话,提示重新下子,如果玩家输入的坐标已经有棋子的话,提示重新下子。
6.人机落子
- 玩家落子之后人机落子
void computerMove(char board[ROW][COL], int row, int col)//~电脑下子
{
while(1)
{
int num1 = rand() % row; //生成随机数并取模row,保证row范围在棋盘大小内
int num2 = rand() % col; //生成随机数并取模COL,保证COL范围在棋盘大小内
if (board[num1][num2] == ' ')
{
board[num1][num2] = '#'; //如果为空落子成功,如果不为空重新生成随机数
break;
}
}
printf("人机落子并说道:你输定了小伙子\n");
}
7.判断输赢
- 判断输赢是很重要的一步,不论是玩家落子后或电脑落子后,我们都应该进行判断程序是否应该结束
char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束
{
for (int i = 0; i < ROW; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
{
return board[0][i]; //列相等返回所在列的字符,游戏结束
}
}
for (int i = 0; i < COL; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
{
return board[i][1];//行相等返回所在行的字符,游戏结束
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
{
return board[1][1];//斜线相等返回所在字符,游戏结束
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
{
return board[1][1];//斜线相等返回所在字符,游戏结束
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
{
return; //如果还有空位,则游戏继续
}
}
}
return 'q';//运行到这里证明棋盘已经满了,游戏结束
}
8.game函数
- 最后我们根据这些函数的作用将所有的函数整合到一块,就形成了我们整个游戏程序
void game()
{
char board[ROW][COL] = { 0 }; //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘
init(board, ROW, COL); //此函数用于二维数组初始化
printboard(board, ROW, COL); //~用于打印棋盘
while (1)
{
char end = '\0';
playerMove(board, ROW, COL); //~玩家下子
printboard(board, ROW, COL); //~打印棋盘
end = ending(board, ROW, COL); //查看是否应该结束
if (end == '*') //返回值为*玩家胜利
{
printf("Player WIN!!!\n");
break;
}
else if (end == 'q') //返回值为棋盘满了未分胜负,平局,退出游戏
{
printf("敌人太强大了,居然平分秋色\n");
}
computerMove(board, ROW, COL); //~电脑下子
printboard(board, ROW, COL); //打印棋盘
end = ending(board, ROW, COL); //查看是否应该结束
if (end == '#') //返回值为#人机获得胜利
{
printf("Computer WIN!!!\n");
break;
}
else if (end == 'q')
{
printf("平局\n");
}
}
}
文件分类
🌞🌞为了使代码更有阅读性,我们不建议把所有函数写在一个文件里,所以这里分成三个文件
test.c
- 这个文件包含程序的主体构思,程序用到的一系列函数我们封装在其他文件夹,这里只需要引入头文件即可
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu() //菜单
{
printf("****************************\n");
printf("****** 1. play *****\n");
printf("****** 0. exit *****\n");
printf("****************************\n");
}
void game()
{
char board[ROW][COL] = { 0 }; //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘
initboard(board, ROW, COL); //此函数用于二维数组初始化
printboard(board, ROW, COL); //~用于打印棋盘
while (1)
{
char end = '\0';
playerMove(board, ROW, COL); //~玩家下子
printboard(board, ROW, COL); //~打印棋盘
end = ending(board, ROW, COL); //查看是否应该结束
if (end == '*')
{
printf("Player WIN!!!\n");
break;
}
else if (end == 'q')
{
printf("敌人太强大了,居然平分秋色\n");
}
computerMove(board, ROW, COL); //~电脑下子
printboard(board, ROW, COL); //打印棋盘
end = ending(board, ROW, COL); //查看是否应该结束
if (end == '#')
{
printf("Computer WIN!!!\n");
break;
}
else if (end == 'q')
{
printf("平局\n");
}
}
}
int main()
{
int input = 0;
srand((unsigned)time(NULL)); //生成随机数用于人机自动落子
do
{
menu(); //do-while语句进来先打印菜单栏
printf("请进行选择(0/1)\n"); //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了
scanf("%d", &input);
switch (input) //switch语句进行选择,一目了然
{
case 1:
game(); //进入游戏
break;
case 0:
printf("成功退出");
break;
default:
printf("输入错误,请重新输入");
break;
}
} while (input);
}
game.c
- 进入游戏后需要的所有函数都封装在这里
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void initboard(char board[ROW][COL],int row,int col)//此函数用于二维数组初始化
{
memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}
void printboard(char board[ROW][COL],int row,int col)//~用于打印棋盘
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j<col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < COL - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
void playerMove(char board[ROW][COL], int row, int col)//~玩家下子
{
printf("该你了,请选择坐标(?,?)\n");
while (1)
{
int num1=0;
int num2=0;
scanf("%d,%d", &num1, &num2);
if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0))
{
printf("请输入正确位置");
continue;
}
if (board[num1-1][num2-1] == ' ')
{
board[num1-1][num2-1] = '*';
break;
}
else
{
printf("请选择空位下子\n");
}
}
}
void computerMove(char board[ROW][COL], int row, int col)//~电脑下子
{
while(1)
{
int num1 = rand() % row;
int num2 = rand() % col;
if (board[num1][num2] == ' ')
{
board[num1][num2] = '#';
break;
}
}
printf("你输定了小伙子\n");
}
char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束
{
for (int i = 0; i < ROW; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
{
return board[0][i]; //列相等返回所在列的字符,游戏结束
}
}
for (int i = 0; i < COL; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
{
return board[i][1];//行相等返回所在行的字符,游戏结束
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
{
return board[1][1];//斜线相等返回所在字符,游戏结束
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
{
return board[1][1];//斜线相等返回所在字符,游戏结束
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
{
return; //如果还有空位,则游戏继续
}
}
}
return 'q';//运行到这里证明棋盘已经满了
}
game.h
- 将;主程序所需要的函数全部在头文件中声明,增加代码阅读性
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#define COL 3
#define ROW 3
void printboard(char board[ROW][COL], int row, int col);//~用于打印棋盘
void initboard(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 ending(char board[ROW][COL], int row, int col);//查看是否应该结束
撒花
这就是实现三子棋的全部内容了,创作不易,还请各位小伙伴多多点赞关注,以后也会更新各种小游戏还有关于c语言的博客。