手把手教你C语言实现《三子棋游戏》

文章目录

  • 1.介绍
  • 2.构思
  • 3.代码
    • 开始界面与主程序
    • game函数
    • 初始化函数
    • 打印函数
    • 玩家下棋
    • 电脑下棋
    • 判断输赢
    • game.h
  • 完整版

1.介绍

想必三字棋大家都玩过吧!
如图所示,大家一下子就明白了。
那么如何通过代码实现这个小游戏呢?
来,跟着我一步步操作。

2.构思

当你想写一个程序,首先我们要分析他的流程:

  1. 我们在一个格子里下棋。
  2. 我们下一个棋,紧接着电脑下一个棋。
  3. 判断胜负。

以上是大体的三子棋流程,头脑里有一个大概,接下来我们开始写代码。

3.代码

开始界面与主程序

首先我们打印开始界面:

void menu()
{
	printf("*************************\n");
	printf("*****   1. play    ******\n");
	printf("*****   0. exit    ******\n");
	printf("*************************\n");
}

接下来写主程序:

int main()
{
	int input = 0;
	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}
  • 这里选择do-while语句更符合游戏“先执行后判断”的特点。
  • 配合switch-case语句构成了游戏开始界面的功能。
  • 在case1下我预先写了游戏运行函数game(),接下来我们开始填充game()函数。

game函数

void game()
{
	char board[ROW][COL];
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
}

首先创建一个text.c文件,我们定义一个数组char board[ROW][COL]用于存放我们下棋的棋子,这里选择使用#define 定义ROW为行数,COL为列数,方便更改棋盘尺寸。然后定义初始化函数InitBoard和打印函数DisplayBoard,同时我们再创建一个game.c文件存放创建的自定义函数。

初始化函数

void InitBoard(char board[ROW][COL], int row, int col)
{
	int i;
	for (i = 0; i < row; i++) {
		int j;
		for (j = 0; j < col; j++) {
			board[i][j] = ' ';
		}
	}
}

在棋盘每个位置放置空格表示没有棋子。

打印函数

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i;
	int j;
	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");
	}
	printf("\n");
}

运用for语句嵌套打印出我们想要的棋盘形状。
手把手教你C语言实现《三子棋游戏》_第1张图片
将以上两个函数存放到text.c的game函数中,同时我开始构建玩家下棋的代码。

void game()
{
	char board[ROW][COL];
	char ret = 0;
	
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
	
	while (1) {
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		}
	}
}

这里我们定义了玩家下棋函数PlayerMove和电脑下棋函数ComputerMove,每次下完棋我们需要看到棋下在哪了,所以每次下棋之后都需要调用DisplayBoard函数打印到屏幕。

玩家下棋

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x, y;
	while (1) {
		printf("请输入要下棋的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 0 && x <= row && y >= 0 && y <= col) {
			if (board[x - 1][y - 1] == ' ') {
				board[x-1][y-1] = '*';
				break;
			}
			else {
				printf("该坐标被占用,请输入其他坐标\n");
			}
		}
		else {
			printf("该坐标非法,请重新输入。\n");
		}
	}
}

首先输入想下棋的坐标x ,y,然后判断当x,y满足在棋盘内坐标合法。
当坐标合法时判断下棋前该坐标为空格,则在该坐标下棋。
如果该坐标已经有棋了,则打印"该坐标被占用,请输入其他坐标"进行提示。
下完棋通过break结束运行。
注意!!!
玩家下棋时输入的坐标跟数组定义的坐标不一样,所以判断玩家的坐标时需要将坐标减一进行判断。

电脑下棋

void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋\n");
	while (1) {
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ') {
			board[x][y] = '#';
			break;
		}
	}
}

这里调用rand函数生成随机数,通过% row % col限制随机数范围不得超过棋盘大小。用if语句判断在没人下棋的地方下棋(即空格处),下完棋通过break结束运行。

记得在主函数添加srand((unsigned int)time(NULL));
srand设置随机数生成器,调用time函数作为种子,time函数返回值为time_z,所以通过unsigned int强制类型转换。rand和srand存放于#include

我们将以上两个下棋函数放到game函数内

void game()
{
	char board[ROW][COL];
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
	while (1) {
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
	}
}

判断输赢

static int IsFull(char board[ROW][COL], 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;
}

char IsWin(char board[ROW][COL],int row,int col)
{
	for (int 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];
		}
	}

	for (int i = 0; i < col; i++)
	{
		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[1][1] != ' ')
	{
		return board[1][1];
	}

	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	if (IsFull(board, row, col))
		return 'Q';

	return 'C';
}

我们定义IsWin判断输赢和IsFull判断平局。
三个棋连成一条直线则赢,所以利用坐标进行判断。
如果每个格子都有棋,但不能判断输赢,则为平局。
我们定义ret变量接收IsFull函数返回值判断输赢
玩家赢 - ’ * ',电脑赢 - ’ # ',平局 — ’ Q ‘,游戏继续-’ C ’

void game()
{
	char board[ROW][COL];
	char 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);
		ret = IsWin(board, ROW, COL);
		if (ret != 'C') {
			break;
		}
	}
	if (ret == '*') {
		printf("玩家赢了\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢了\n");
	}
	else
	{
		printf("平局\n");
	}
}

每次玩家和电脑下完棋,都需要分别进行判断输赢。

game.h

我们可以创建一个game.h头文件包含我们所用的库函数和自定义函数。
每次通过#include "game.h"调用。

#include 
#define ROW 3
#define COL 3
#include 
#include 
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]);

完整版

text.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];
	char 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);
		ret = IsWin(board, ROW, COL);
		if (ret != 'C') {
			break;
		}
	}
	if (ret == '*') {
		printf("玩家赢了\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢了\n");
	}
	else
	{
		printf("平局\n");
	}
}

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");
			break;
		}
	} while (input);
	return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i;
	for (i = 0; i < row; i++) {
		int j;
		for (j = 0; j < col; j++) {
			board[i][j] = ' ';
		}
	}
}

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i;
	int j;
	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");
	}
	printf("\n");
}

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x, y;
	while (1) {
		printf("请输入要下棋的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 0 && x <= row && y >= 0 && 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)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋\n");
	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, j;
	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)
{
	for (int 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];
		}
	}

	for (int i = 0; i < col; i++)
	{
		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[1][1] != ' ')
	{
		return board[1][1];
	}

	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	if (IsFull(board, row, col))
		return 'Q';

	return 'C';
}

game.h

#pragma once
#include 
#define ROW 3
#define COL 3
#include 
#include 
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]);

你可能感兴趣的:(详解C语言,c语言,游戏)