三子棋相信我们大多数人都玩过,这是一款操作简单易上手的电脑益智小游戏,我们今天尝试一下用c语言来实现它
- 基本思路
三子棋的基本规则是游戏双方之一将其三个棋子连成一条线(横向、纵向或对角线)就获胜或者游戏双方的棋子将整个棋盘填满也没有达成连线,此时达成平局
- 具体代码
规则简单易懂,接下来我们就一起看看具体的实现步骤吧!
首先,我们需先创建一个游戏菜单并实现简单的进入与退出游戏功能
void menu()
{
printf("******************************************\n");
printf("【------- 欢迎进入三子棋游戏 -------】\n");
printf("******************************************\n");
printf("-----------> 1.play <------------\n");
printf("-----------> 2.exit <------------\n");
printf("******************************************\n");
}
menu()函数用来实现游戏主菜单界面的打印,效果如下:
我们可以看到主菜单有进入游戏和退出游戏两个选项,在此我们设计一个变量用于接收用户的的选择。用do-while循环体实现用户多次游戏的功能并对其不同的选择进行判断。
int main()
{
int input = 0;
do
{
srand((unsigned)time(NULL));//生成随机数
menu();
printf("请选择:>");//玩家根据菜单进行选择
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
当用户输入1时,跳出循环并启动游戏
当用户选择0时,跳出循环并退出游戏
当用户输入1和0以外的数时,返回错误并提醒重新选择
接下来就是程序的重点——游戏主体。
首先,我们需要创建game()函数
void game()
{
}
我们可以将棋盘视为一个二维字符数组,行定义为ROW,列定义为COL
char board[ROW][COL] = { 0 };
在这里我们以三子棋为例,后期如果想增加游戏难度将棋盘扩展时可以将二维数组的行和列用宏定义置于头文件便于修改。
#define ROW 3
#define COL 3
二维数组建好后用InitBoard()函数对其进行初始化操作,代码如下:
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] = ' ';
}
}
}
接下来,我们通过一个DisplayBoard()棋盘打印函数查看初始化结果,代码如下:
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 < col - 1)//打印"#"形棋盘
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0;j < col;j++)
{
printf("---");
if(j<col-1)
{
printf("|");
}
}
printf("\n");
}
}
}
此处展示一下棋盘界面:
为了让游戏更具有人性化,在此我们实现一个功能:由用户来选择电脑先走或玩家先走功能,用switch-case语句实现不同模式下的路径选择,代码如下:
printf("请选择:1.电脑先走 2.玩家先走\n");
scanf("%d", &s);
switch (s)
{
case 1:
printf("电脑走\n");
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);//电脑走并打印棋盘
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
case 2:
printf("玩家走\n");
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
}
用户选择后我们正式开始玩游戏啦! (这里我们假设用户选择电脑先走)
既然三子棋是个人机游戏,那我们就需要让电脑自己走,最好达到一个"出棋不意"的效果。这里我们利用srand()函数使得电脑自动生成随机数二维坐标值(此处我们不需要它反复生成随机值,一次就够用了),这样游戏就更具有趣味性了。
srand((unsigned)time(NULL));
为电脑走程序创建一个函数ComputerMove(),其代码如下(此处我们将电脑的棋子设为" * "):
void ComputerMove(char board[ROW][COL], int row, int col)
{
while (1)
{
int x = rand() % ROW;
int y = rand() % COL;//创建随机坐标
if ((x - 1 >= 0) && (x - 1 < row) && (y - 1 >= 0) && (y - 1 < col))
{
if (' ' == board[x][y])//判断当前位置是否为空
{
board[x][y] = '*';
break;
}
}
}
}
注意:在程序中数组下标由0开始,而面向普通用户时我们输入坐标习惯以1开始,所以此处坐标值都要-1,注意棋盘边界,所输入的坐标必须小于其最大行、列数
电脑走完轮到玩家走了,创建函数PlayerMove()实现此功能,代码如下:
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请玩家输入坐标:>");
while (1)
{
scanf("%d %d", &x, &y);
if ((x - 1 >= 0) && (x - 1 < row) && (y - 1 >= 0) && (y - 1 < col))
{
if (' ' == board[x - 1][y - 1])
{
board[x - 1][y - 1] = 'o';//玩家走记为"o"
break;
}
else
printf("所选坐标已有棋子,请重新选择坐标:>");
}
else
printf("所输坐标已越界,请重新输入!\n");
}
}
注意:无论是电脑还是玩家落子前,均需要先判断坐标处是否为空,为空则可落子,电脑派生随机数前会自行判断,我们暂可不管,玩家则需要手动输入新的坐标
双方走完后,我们需要判断输赢,创建函数实现对电脑赢、玩家赢、平局三种情况的判断,代码如下:
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 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][1];
}
for (j = 0;j < col;j++)//纵向判断
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
return board[0][j];
}
//对角线判断
if (board[1][1] == board[2][2] && board[2][2] == board[3][3] && board[1][1] != ' ')
return board[1][1];
if(board[1][3] == board[2][2] && board[2][2] == board[3][1] && board[1][3] != ' ')
return board[1][3];
if(IsFull(board, ROW, COL))
return 'Q';//棋盘已满,平局退出
else
return ' ';
}
判断胜利的三个条件:横向连三子、纵向连三子、对角线(" \ “和” / ")连三子
否则棋盘被填满,平局
当然游戏也不是只有输赢,我们也需要一个IsFull()函数来判定是否平局,平局条件:棋盘被填满都无人胜出,代码如下:
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;
}
至此我们已经写出了6个函数来实现游戏板块了,创建game()函数将其调用,实现整个游戏的运行,代码如下:
void game()
{
char board[ROW][COL] = { 0 };
char ret ='0';
int s;
InitBoard(board,ROW,COL);//初始化棋盘
DisplayBoard(board, ROW, COL);//打印棋盘
printf("请选择:1.电脑先走 2.玩家先走\n");
scanf("%d", &s);
switch (s)//玩家选择谁先走
{
case 1:
printf("电脑走\n");
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);//电脑走并打印棋盘
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
case 2:
printf("玩家走\n");
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
}
do
{
printf("玩家走\n");
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
printf("电脑走\n");
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
} while (ret == ' ');//输赢未定游戏循环
if (ret== 'o')
{
printf("玩家赢\n");
}
else if (ret== '*')
{
printf("电脑赢\n");
}
else
{
printf("本局平局\n");
}
}
至此整个游戏程序就基本上写完了,仔细看看其实并不是很难,只需要在脑海中走一遍游戏流程将其写成函数,最终调用就好啦!
下面附上完整代码:
第一部分:game.h头文件
头文件中,我们放入了在源文件里面调用的各种函数,方便后期检测和修改以及精简代码
#ifndef __GAME_H__
#define __GAME_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#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 IsFull(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);
#endif// __GAME_H__
第二部分:game.c源文件
这部分主要放入各函数的具体代码,可以清晰明了的看到每个板块实现的具体步骤
#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 < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0;j < col;j++)
{
printf("---");
if(j<col-1)
{
printf("|");
}
}
printf("\n");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
while (1)
{
int x = rand() % ROW;
int y = rand() % COL;
if ((x - 1 >= 0) && (x - 1 < row) && (y - 1 >= 0) && (y - 1 < col))
{
if (' ' == board[x][y])
{
board[x][y] = '*';
break;
}
}
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请玩家输入坐标:>");
while (1)
{
scanf("%d %d", &x, &y);
if ((x - 1 >= 0) && (x - 1 < row) && (y - 1 >= 0) && (y - 1 < col))
{
if (' ' == board[x - 1][y - 1])
{
board[x - 1][y - 1] = 'o';//玩家走记为"o"
break;
}
else
printf("所选坐标已有棋子,请重新选择坐标:>");
}
else
printf("所输坐标已越界,请重新输入!\n");
}
}
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;
}
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 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][1];
}
for (j = 0;j < col;j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
return board[0][j];
}
if (board[1][1] == board[2][2] && board[2][2] == board[3][3] && board[1][1] != ' ')
return board[1][1];
if(board[1][3] == board[2][2] && board[2][2] == board[3][1] && board[1][3] != ' ')
return board[1][3];
if(IsFull(board, ROW, COL))
return 'Q';
else
return ' ';
}
第三部分:test.c源文件
此部分主要存放menu()、game()函数以及主函数,在这个源文件中我们可以清晰的看到整个三子棋游戏由创建到运行的流程。
注意:此处提醒一点,当调用我们自己创建的头文件时,需要用 双引号 将其括起来:#include “game.h”
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("******************************************\n");
printf("【------- 欢迎进入三子棋游戏 -------】\n");
printf("******************************************\n");
printf("-----------> 1.play <------------\n");
printf("-----------> 2.exit <------------\n");
printf("******************************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
char ret ='0';
int s;
InitBoard(board,ROW,COL);
DisplayBoard(board, ROW, COL);
printf("请选择:1.电脑先走 2.玩家先走\n");
scanf("%d", &s);
switch (s)
{
case 1:
printf("电脑走\n");
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
case 2:
printf("玩家走\n");
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
}
do
{
printf("玩家走\n");
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != ' ')
{
break;
}
printf("电脑走\n");
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
} while (ret == ' ');
if (ret== 'o')
{
printf("玩家赢\n");
}
else if (ret== '*')
{
printf("电脑赢\n");
}
else
{
printf("本局平局\n");
}
}
int main()
{
int input = 0;
do
{
srand((unsigned)time(NULL));
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
以上就是本次我所分享的用C语言实现简易的三子棋小游戏的全部内容了,希望能为你们带来一些收获。小小兵一枚,还有许多不足望请大家多指点!