背景
记得小时候经常和爷爷在水泥地上,随手抓来两颗石子,一边口里念叨“小货兵摆大炮”,一边在地上划下横竖各6条道,然后在从旁边的土地上捡一些小石子和两个大石块,小石子代表小兵,大石块代表大炮。
游戏规则
- 小兵每次可移动一步,方向为前后左右。
- 大炮每次可移动一步,方向为前后左右。当大炮与小兵中间有一个空位,大炮可以选择吃掉小兵。
- 大炮与小兵的移动范围不能超过棋盘边界。
胜利规则
- 当大炮无法移动时,小兵获胜,即小兵把大炮逼到游戏边界处。
- 当小兵被大炮全部干掉时,大炮获胜。
代码实现
-
Bing.h
:代表小兵#ifndef BING_H_ #define BING_H_ #include <iostream> enum class Dir{ Up = 0, Down, Left, Right }; class Bing { private: int x; int y; int length; int width; public: Bing(int _x,int _y); bool Move(Dir dir); std::pair<int,int> getPosition(); ~Bing(); }; #endif
-
Pao.h
:炮#ifndef PAO_H_ #define PAO_H_ #include "Bing.h" class Pao:public Bing { private: public: Pao(int _x,int _y); ~Pao(); }; #endif
-
Game.h:游戏类
#include "Bing.h" #include "Pao.h" #include <vector> class Game { private: int length; int width; int bingRows; int paoNum; int **sence; std::vector<Bing*> bings; std::vector<Bing*> delBings; std::vector<Pao*> paos; public: Game(); void updateSence(); void show(); bool isBingsWin(); bool isPaosWin(); bool MovePao(); bool MoveBing(); void run(); ~Game(); };
-
Game.cpp
游戏类的实现#include <iostream> #include "Game.h" using namespace std; Game::Game() { length = 6; width = 6; bingRows = 3; paoNum = 2; sence = new int*[length]; for(int i=0;i<length;++i){ sence[i] = new int[width]; } for(int i=0;i<bingRows;++i){ for(int j=0;j<width;++j){ Bing* bing = new Bing(i,j); bings.push_back(bing); } } int row = bingRows-1+2; int col = width/2-1; for(int i=0;i<paoNum;++i){ Pao* pao = new Pao(row,col+i); paos.push_back(pao); } } void Game::updateSence(){ for(int i=0;i<length;++i){ for(int j=0;j<width;++j){ sence[i][j] = 0; } } for(int i=0;i<bings.size();++i){ for(auto bing:bings){ auto pos = bing->getPosition(); sence[pos.first][pos.second] = 1; } } for(auto pao:paos){ auto pos = pao->getPosition(); sence[pos.first][pos.second] = 2; } } void Game::show(){ updateSence(); for(int i=0;i<length;++i){ for(int j=0;j<width;++j){ if(sence[i][j] == 1){ printf("* "); }else if(sence[i][j] == 2){ printf("+ "); }else{ printf(" "); } } printf("\n"); } } bool Game::isBingsWin(){ bool flag = true; for(auto pao:paos){ auto pos = pao->getPosition(); auto up = std::make_pair(pos.first-1,pos.second); if(up.first>=0&&up.first<length&&up.second>=0&&up.second<width){ if(sence[up.first][up.second] == 0){ flag = false; } } up = std::make_pair(pos.first+1,pos.second); if(up.first>=0&&up.first<length&&up.second>=0&&up.second<width){ if(sence[up.first][up.second] == 0){ flag = false; } } up = std::make_pair(pos.first,pos.second-1); if(up.first>=0&&up.first<length&&up.second>=0&&up.second<width){ if(sence[up.first][up.second] == 0){ flag = false; } } up = std::make_pair(pos.first,pos.second+1); if(up.first>=0&&up.first<length&&up.second>=0&&up.second<width){ if(sence[up.first][up.second] == 0){ flag = false; } } } return flag; } bool Game::isPaosWin(){ if(bings.size()<4){ return true; } return false; } bool Game::MovePao(){ Pao* pao; printf("请选择你要移动的炮(1/2):"); int x; cin>>x; if(x != 1 && x != 2){ printf("你选择的炮无效,请重新选择!\n"); return false; } pao = paos[x-1]; auto pos = pao->getPosition(); printf("请选择你要进行的操作(移动:1 / 吃兵:2):"); cin>>x; if(x != 1 && x != 2){ printf("你选择的操作无效,请重新选择!\n"); return false; } if(x == 1){ printf("请选择你要移动的方向(上:w /下:s /左:a /右:d):"); char ch; bool flag = false; cin>>ch; if(ch == 'w' || ch == 's' ||ch == 'a' ||ch == 'd'){ switch (ch) { case 'w': if(pos.first > 0 && sence[pos.first-1][pos.second] == 0){ pao->Move(Dir::Up); flag = true; } break; case 's': if(pos.first < length-1 && sence[pos.first+1][pos.second] == 0){ pao->Move(Dir::Down); flag = true; } break; case 'a': if(pos.second > 0 && sence[pos.first][pos.second-1] == 0){ pao->Move(Dir::Left); flag = true; } break; case 'd': if(pos.second < width-1 && sence[pos.first][pos.second+1] == 0){ pao->Move(Dir::Right); flag = true; } break; default: break; } } if(flag){ return true; } else{ printf("你选择的方向无效,请重新选择!\n"); return false; } }else if(x == 2){ printf("请选择你要移动的方向(上:w /下:s /左:a /右:d):"); char ch; bool flag = false; cin>>ch; if(ch == 'w' || ch == 's' ||ch == 'a' ||ch == 'd'){ switch (ch) { case 'w': if(pos.first > 1 && sence[pos.first-2][pos.second] == 1 && sence[pos.first-1][pos.second] == 0){ pao->Move(Dir::Up); pao->Move(Dir::Up); pos = pao->getPosition(); auto begin = bings.begin(); while (begin != bings.end()) { if(pos == (*begin)->getPosition()){ delBings.push_back(*begin); bings.erase(begin); break; } begin++; } flag = true; } break; case 's': if(pos.first < length-2 && sence[pos.first+2][pos.second] == 1 && sence[pos.first+1][pos.second] == 0){ pao->Move(Dir::Down); pao->Move(Dir::Down); pos = pao->getPosition(); auto begin = bings.begin(); while (begin != bings.end()) { if(pos == (*begin)->getPosition()){ delBings.push_back(*begin); bings.erase(begin); break; } begin++; } flag = true; } break; case 'a': if(pos.second > 1 && sence[pos.first][pos.second-2] == 1 && sence[pos.first][pos.second-1] == 0){ pao->Move(Dir::Left); pao->Move(Dir::Left); pos = pao->getPosition(); auto begin = bings.begin(); while (begin != bings.end()) { if(pos == (*begin)->getPosition()){ delBings.push_back(*begin); bings.erase(begin); break; } begin++; } flag = true; } break; case 'd': if(pos.second < width-2 && sence[pos.first][pos.second+2] == 1 && sence[pos.first][pos.second+1] == 0){ pao->Move(Dir::Right); pao->Move(Dir::Right); pos = pao->getPosition(); auto begin = bings.begin(); while (begin != bings.end()) { if(pos == (*begin)->getPosition()){ delBings.push_back(*begin); bings.erase(begin); break; } begin++; } flag = true; } break; default: break; } } if(flag){ return true; } else{ printf("你选择的方向无效,请重新选择!\n"); return false; } } } bool Game::MoveBing(){ printf("请选择你要移动的兵的位置(x,y):"); int x,y; cin>>x>>y; if(x>0&&x<=length&&y>0&&y<=width&&sence[x-1][y-1]==1){ }else{ printf("你选择的位置无效,请重新选择!\n"); return false; } std::pair<int,int> pos(x-1,y-1); Bing* b; for(auto bing:bings){ if(pos == bing->getPosition()){ b = bing; break; } } printf("请选择你要移动的方向(上:w /下:s /左:a /右:d):"); char ch; cin>>ch; bool flag = false; switch (ch) { case 'w': if(pos.first>0&&sence[pos.first-1][pos.second] == 0){ b->Move(Dir::Up); flag = true; } break; case 's': if(pos.first<length-1&&sence[pos.first+1][pos.second] == 0){ b->Move(Dir::Down); flag = true; } break; case 'a': if(pos.second>0&&sence[pos.first][pos.second-1] == 0){ b->Move(Dir::Left); flag = true; } break; case 'd': if(pos.second<width-1&&sence[pos.first][pos.second+1] == 0){ b->Move(Dir::Right); flag = true; } break; default: break; } if(!flag){ printf("你选择的方向无效,请重新选择!\n"); } return flag; } void Game::run(){ while(true){ system("clear"); show(); if(isBingsWin()){ printf("小兵获胜!\n"); break; } while (!MovePao()){} system("clear"); show(); if(isPaosWin()){ printf("大炮获胜!\n"); break; } while (!MoveBing()){} } } Game::~Game() { for(auto bing:bings){ delete bing; } for(auto bing:delBings){ delete bing; } for(auto pao:paos){ delete pao; } }
-
main.cpp
#include <iostream> #include "Game.h" using namespace std; int main(){ Game* g = new Game(); g->run(); g->~Game(); return 0; }
实现效果
-
游戏开始界面,炮先行
-
当炮吃掉一个小兵后的游戏场景
-
小兵移动的方式
后记
这个小游戏做完后,和朋友试玩了一下,发现有个bug,然后修正了。又试玩了一局,I win!
下一个小游戏做连连看吧!
(想要源码的,可以私信我!)