C++實現(xiàn)五子棋游戲(注釋版)
本文實例為大家分享了C++實現(xiàn)五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
本程序是在vs2015環(huán)境下編譯運行
vs左上角:文件–新建–項目–Win32控制臺應(yīng)用程序–(注意勾選“附加選項:空項目“)
右鍵頭文件”添加–新建項“,類型為 .h 文件,名稱分別為”Player.h“以及”ChessBoard.h",即定義“玩家”和“棋盤”兩個class
然后相同的方式在源文件中右鍵添加三個.cpp文件
然后把code copy過去就可以了
另外,代碼不是完美的,存在bug,大家可以嘗試找一下
相關(guān)文檔已上傳,可自行下載查看
//main.cpp #include<cstdio> #include"ChessBoard.h" //包含入需要的各類頭文件,除了需要的標準庫頭文件,還需要我們自定義的兩個類頭文件,使得兩個類對全段程序可見 #include"Player.h" int main() { ?? ?ChessBoard board; ? ? ? ? ? ?//定義了棋盤對象board,思考該對象的構(gòu)造過程 ?? ?Player playA("aaa", '*'); ? ?//玩家aaa的棋子形狀是'*' ?? ?playA.attachToBoard(&board); // 這里將棋盤對象board的地址賦給了playA玩家對象的成員變量指針m_ptBoard??! ?? ?Player playB("bbb", '#'); ? ?//玩家bbb的棋子形狀是'#' ?? ?playB.attachToBoard(&board); // 這里將棋盤對象board的地址賦給了playB玩家對象的成員變量指針m_ptBoard!! ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 這里查看玩家對象的棋盤成員對象指針值是否一致,與board對象地址是否一致! ?? ?board.show(); ?? ?while (1) ?? ?{ ?? ??? ?playA.setChess(); //玩家A放下一個棋子 ?? ??? ?if (playA.isWin()) ?//玩家A落棋后自己當裁判判斷是否可以結(jié)束戰(zhàn)斗 ?? ??? ?{ ?? ??? ??? ?cout << "Winer!"; break; ?? ??? ?} ?? ??? ?board.show(); ? //注意該過程board對象,和AB棋盤對象的內(nèi)容同時變化 ?? ??? ?playB.setChess(); ?//玩家B放下一個棋子 ?? ??? ?if (playB.isWin()) ? //玩家B落棋后自己當裁判判斷是否可以結(jié)束戰(zhàn)斗 ?? ??? ?{ ?? ??? ??? ?cout << "Winer!"; break; ?? ??? ?} ?? ??? ?board.show(); //注意該過程board對象,和AB棋盤對象的內(nèi)容同時變化 ?? ?} ?? ?//getchar(); ?? ?return 1; }
//ChessBoard.cpp #include"ChessBoard.h" ChessBoard::ChessBoard() { ?? ?for (int i = 1; i<ROW - 1; i++) ?? ?for (int j = 1; j<COL - 1; j++) ?? ??? ?m_cSquare[i][j] = ' '; ?? ?for (int j = 0; j<COL; j++) ?? ??? ?m_cSquare[0][j] = m_cSquare[ROW - 1][j] = '-'; ?? ?for (int i = 1; i<ROW; i++) ?? ??? ?m_cSquare[i][0] = m_cSquare[i][COL - 1] = '|'; } void ChessBoard::show() { ?? ?system("cls"); ?? ?for (int i = 0; i<ROW; i++) ?? ?{ ?? ??? ?for (int j = 0; j<COL; j++) ?? ??? ??? ?cout << m_cSquare[i][j] << ' '; ? //這里的“ <<' ' ”很重要,這樣才能使屏幕上ROW*COL輸出為方形 ?? ??? ?cout << endl; ?? ?} }
//ChessBoard.h #pragma once #include<iostream> using namespace std; #define ROW 15 ?// 棋盤行和列定義常數(shù) #define COL 15 class ChessBoard//棋盤類 { public: ?? ?char m_cSquare[ROW][COL]; public: ?? ?ChessBoard(); //構(gòu)造函數(shù) ?? ?void show(); ?//棋盤畫圖顯示 };
//player.cpp #include"Player.h" bool Player::isInChessBoard(int x, int y) { ?? ?if (x<ROW - 1 && x>0 && y<COL - 1 && y>0) ?? ??? ?return true; ?? ?else ?? ??? ?return false; } /*下面是核心代碼:如何判斷五子是否連成線。 這里采用的是以玩家此刻放下的棋子為中心,從四種方向逐個判斷是否在此方向上連成了線 這里將四個方向上的判斷都放在一起,避免了四次調(diào)用不同方向上的判斷, 但在for里面放一個switch有些別扭,可讀性上似乎不好*/ bool Player::isLine(int x, int y) { ?? ?for (int direc = HORIZON; direc <= LEFTTOPTORIGHTBOTTOM; direc++)//四個方向,權(quán)宜之計 ?? ?{ ?? ??? ?int tempX, tempY, cnt = 1;//cnt:連續(xù)排列的同種類的棋子的個數(shù),達到五個則該方贏 ?? ??? ?for (int i = -4; i <= 4; i++) ?? ??? ?{ ?? ??? ??? ?if (i == 0)continue;//此時循環(huán)一遍相當于什么都沒做 ?? ??? ??? ?switch (direc) ?? ??? ??? ?{ ?? ??? ??? ?case HORIZON: ?? ??? ??? ??? ?tempX = x; ?tempY = y + i; ? break; ?? ??? ??? ?case VERTICAL: ?? ??? ??? ??? ?tempX = x + i; tempY = y; ? ?break; ?? ??? ??? ?case LEFTBOTTOMTORIGHTTOP: ?? ??? ??? ??? ?tempX = x - i; tempY = y + i; ? break; ?? ??? ??? ?case LEFTTOPTORIGHTBOTTOM: ?? ??? ??? ??? ?tempX = x + i; tempY = y + i; ? break; ?? ??? ??? ?} ?? ??? ??? ?if (isInChessBoard(tempX, tempY) && m_ptBoard->m_cSquare[tempX][tempY] == m_chessType) /*判斷關(guān)鍵理解下該句子邏輯*/ ?? ??? ??? ??? ?cnt++; ?? ??? ??? ?else ?? ??? ??? ??? ?cnt = 0; ?? ??? ??? ?if (cnt == 5)//五子成線 ?? ??? ??? ??? ?return true; ?? ??? ?} ?? ?}return false; } void Player::setChess() { ?? ?cout << "請輸入玩家" << m_name << "的x坐標和y坐標:" << endl; ?? ?cin >> m_x >> m_y; ?? ?while (cin.fail() || m_ptBoard->m_cSquare[m_x][m_y] != ' ')//輸入不是int型變量或者此位置上已有棋子 ?? ?{ ?? ??? ?cout << "輸入有誤,請再次輸入玩家" << m_name << "的x坐標和y坐標:" << endl; ?? ??? ?cin.clear(); ?//清除fail狀態(tài)? ?? ??? ?cin.sync() ; ?//清除緩沖區(qū) ?? ??? ?cin >> m_x >> m_y; ?? ?} ?? ?if (isInChessBoard(m_x, m_y)) ?? ??? ?m_ptBoard->m_cSquare[m_x][m_y] = m_chessType; } bool Player::isWin() { ?? ?return isLine(m_x, m_y) ? true : false; }
//player.h #pragma once //宏定義四種檢測五子是否連成線的方向,常量定義,也可以考慮使用const或者枚舉類型定義! #define HORIZON ?0 #define VERTICAL ?1 #define LEFTBOTTOMTORIGHTTOP 2 #define LEFTTOPTORIGHTBOTTOM 3 #include"ChessBoard.h" #include<iostream> using namespace std; #include<string> class Player { private: ? ?/*私有變量,受保護,不希望被直接訪問,不能訪問嗎?*/ ?? ?string m_name; ? ?/*對象棋手名字成員變量*/ ?? ?char m_chessType; ? ? /*黑白棋變量定義,本案例中*和#定義不同的持子雙方*/ ?? ?int m_x; ? ? ? ? ? ? ? ? ? ? ? ? ?? ?int m_y; ? ? /*下子坐標成員變量*/ ?? ?ChessBoard* m_ptBoard; ? ?/*定義棋盤對象指針*/ public: ?? ?Player(string name, char chessType) :m_name(name), m_chessType(chessType), m_ptBoard(NULL){} /*構(gòu)造函數(shù)*/ ?? ?void attachToBoard(ChessBoard* ptBoard){ m_ptBoard = ptBoard; } /*給成員棋盤對象指針賦值*/ ?? ?bool isInChessBoard(int x, int y); ?/*判斷下棋位置(x,y)是否合理,思考哪些合理,哪些不合理*/ ?? ?bool isLine(int x, int y); ? /*判斷落子是否排成line*/ ?? ?bool isWin(); ? ?/*判斷輸贏*/ ?? ?void setChess(); ?/*下子*/ };
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言數(shù)據(jù)結(jié)構(gòu)不掛科指南之隊列詳解
這篇博客主要介紹一下隊列的概念,并且采用 C 語言,編寫兩種存儲實現(xiàn)方式:順序存儲和鏈式存儲,當然還有常規(guī)的隊列基本操作的實現(xiàn)算法2022-09-09C語言使用ffmpeg實現(xiàn)單線程異步的視頻播放器
這篇文章主要為大家詳細介紹了C語言如何使用ffmpeg實現(xiàn)單線程異步的視頻播放器功能,文中的示例代碼講解詳細,感興趣的小伙伴可以嘗試一下2022-12-12C語言變長數(shù)組 struct中char data[0]的用法詳解
下面小編就為大家?guī)硪黄狢語言變長數(shù)組 struct中char data[0]的用法詳解。小編覺得挺不錯的現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01QT自定義QTextEdit實現(xiàn)大數(shù)據(jù)的實時刷新顯示功能實例
TextEdit是我們常用的Qt控件,用來顯示文本信息,下面這篇文章主要給大家介紹了關(guān)于QT自定義QTextEdit實現(xiàn)大數(shù)據(jù)的實時刷新顯示功能的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-05-05C++類的靜態(tài)成員變量與靜態(tài)成員函數(shù)詳解
下面小編就為大家?guī)硪黄狢++類的靜態(tài)成員變量與靜態(tài)成員函數(shù)的文章。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2021-11-11