C语言实现三子棋(详细讲解+源码)

0 阅读7分钟

前言

C语言实现三子棋是结合我们对数组,函数,循环与分支等内容的考察。通过本篇文章你将学会如何制作出三子棋,看完相信你肯定能够掌握三子棋(文末附三子棋全部代码)


一、游戏规则

1、人和电脑双方轮流在格子里落子下棋,率先连成三个一线的视为胜利

2、棋盘被摆满棋子仍未分出胜利,视为平局

3、当未分出胜负时、可以再来一局

二、所需文件

三子棋并不是一项容易的代码,需要我们进行分文件编写。

如何分文件编写呢,我们可以把程序代码划分成多个文件,不要所有的代码都放在main.c里面,采用分模块的编程思想,进行功能划分,把每个功能不一样的单独放在一个c文件里,然后写头文件把它封装成可调用的一个函数,在主函数调用这个封装好的函数,编译的时候一起编译

好处:

1.功能划分清晰
2.方便调试,找出bug
3.主程序简洁,利于观看

来让给我们看看具体操作如下:
头文件中创建game.h ----用来进行函数的声明
源文件中创建game.c—函数具体实现 / test.c—主题流程

三.创建菜单

在开始前,我们需要先创建一个菜单,虽然创建菜单后不利于调试各个模块,但是在三子棋,扫雷游戏这些少功能模块的可以先创建菜单。

​编辑

用do while循环实现菜单使用,switch语句进行菜单选择,然后进行调试观察菜单能不能正常打印

​编辑


四,游戏核心内容实现
1.创建棋盘并初始化

棋盘实质是一个二维数组

在game.h里面定义ROW和COL分别表示行和列

​编辑

​编辑

2.棋盘打印

再设计一个函数把棋盘打印出来,不是很会描述,大抵情况如下图所示,棋盘打印可以用row,col来弄便于以后修改成多子棋

​编辑

3.玩家下棋

创建一个函数,因为玩家不一定知道数组下标是从零开始的,所以我们可以设置一下,让玩家输入的坐标变成对应二维数组的坐标

​编辑

4、电脑下棋

使用rand函数随机生成一个数,再对row,col取模,得到0到row,col之间的数,为电脑下棋的坐标

在game.c文件中实现电脑下棋函数。电脑随机下棋需要随机坐标引头文件#include <stdlib.h>,随机数生成需要头文件#include <time.h>。将电脑所下棋控制在棋盘内然后判断是否下在空棋盘内否则重下,while实现玩家下错棋子重新下直到下正确退出循环

​编辑

​编辑

5.胜负判断

当棋盘满了的时候,电脑没有地方下棋,就会进入死循环,因此我们需要判断一下游戏的胜负。

三种情况:玩家赢,电脑赢,平局

​编辑

​编辑

判断输赢的函数

char is_win(char board[ROW][COL], int row, int col)
{
	int i = 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][0];
		}

	}
	//判断列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i]&& board[1][i] == board[2][i]&& board[0][i]!=' ')
		{
			return board[1][i];
		}

	}
	//对角线判断
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] == board[2][2] && board[0][0] != ' ')
	{
		return board[0][0];
	}
	if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	//平局,创建is-full函数判断棋盘是否满了
	if (is_full(board, ROW, COL))
		return 'C';
	return 'D';
}

6.game()函数内部具体实现
void game()
{
	
	char board[ROW][COL];
	//初始化棋盘的函数
	Init_board(board, ROW, COL);
	//打印棋盘
	Print_board(board, ROW, COL);
	while (1) {
		//玩家下棋
		player_move(board, ROW, COL);
		Print_board(board, ROW, COL);
		//判断输赢:玩家赢为*,电脑赢为#,平局为C,游戏继续为D
		ret = is_win(board, ROW, COL);
			if (ret != 'D')
			{
				break;
		     }
		//电脑下棋
		computer_move(board, ROW, COL);
		Print_board(board, ROW, COL);
		
	}
	if (ret == '*')
		printf("玩家赢\n"); 
	else if (ret == '#')
		printf("电脑赢\n"); 
	else if (ret =='C')
		printf("平局\n");

	

}

7演示

​编辑

​编辑

8.源码
game.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ROW 3//行
#define COL 3//列
//棋盘初始化和打印
void Init_board(char board[ROW][COL], int row, int col);
void Print_board(char board[ROW][COL], int row, int col);
//玩家和电脑下棋
void player_move(char board[ROW][COL], int row, int col);
void computer_move(char board[ROW][COL], int row, int col);
//判断输赢
char is_win(char board[ROW][COL], int row, int col);
//判断是否满了
int is_full(char board[ROW][COL], int row, int col);

test.c
#include"game.h"
char ret;
void menu()
{

	printf("**********************************\n");
	printf("**** 1、开始游戏 0、退出游戏 *****\n");
	printf("**********************************\n");
}
void game()
{
	
	char board[ROW][COL];
	//初始化棋盘的函数
	Init_board(board, ROW, COL);
	//打印棋盘
	Print_board(board, ROW, COL);
	while (1) {
		//玩家下棋
		player_move(board, ROW, COL);
		Print_board(board, ROW, COL);
		//判断输赢:玩家赢为*,电脑赢为#,平局为C,游戏继续为D
		ret = is_win(board, ROW, COL);
			if (ret != 'D')
			{
				break;
		     }
		//电脑下棋
		computer_move(board, ROW, COL);
		Print_board(board, ROW, COL);
		
	}
	if (ret == '*')
		printf("玩家赢\n"); 
	else if (ret == '#')
		printf("电脑赢\n"); 
	else if (ret =='C')
		printf("平局\n");

	

}
void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:printf("三子棋,启动:\n");
			game();
			 break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("没有该选项,请重新选择\n");
			break;

		}


	} while (input);
}
int main()
{
	test();
	return 0;
}

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


}
void Print_board(char board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		/*printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		if(i<row-1)
		printf("---|---|---\n");*/
		
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < row - 1)
				printf("|");
		}
		printf("\n");
		if (i < row - 1) 
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");

		}
	}
}
void player_move(char board[ROW][COL], int row, int col)
{
	int x, y;
	printf("玩家下棋");
	printf("请输入要下棋的坐标:");
	while (1) {
		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");
			
		}
	}
	



}
void computer_move(char board[ROW][COL], int row, int col)
{
	
	printf("电脑下棋:\n");
	
	while (1)
	{//随机生成坐标
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] ='#';
			break;
		}
	}	
}
//在is win函数中实现,也可以不在头文件中声明
int is_full(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 is_win(char board[ROW][COL], int row, int col)
{
	int i = 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][0];
		}

	}
	//判断列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i]&& board[1][i] == board[2][i]&& board[0][i]!=' ')
		{
			return board[1][i];
		}

	}
	//对角线判断
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] == board[2][2] && board[0][0] != ' ')
	{
		return board[0][0];
	}
	if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	//平局,创建is-full函数判断棋盘是否满了
	if (is_full(board, row, col) == 1)
	{
		return 'C';
	}
		
	return 'D';
}

总结

本次三子棋学习告一段落,你学会了吗。

将三子棋详解和完整代码,反复阅读,坚持每天练习,为未来编写更高级的代码打下夯实的基础,相信你一定可以做到。

有不足的地方也可以指出来,我会虚心接受和改进的