게임 프로그래밍 : C++에서 퍼즈 드라를 만들어 보았습니다.
개요
콘솔 게임 프로그래밍은 네 번째입니다.
이번은 퍼즈드라입니다만, 이쪽도 예에 새지 않고 한 적이 없는 게임입니다.
이런 말하면 게임 좋아하는 분들로부터 화가 난다고 생각합니다만, 게임 하는 분은 그다지 재미있다고 생각되지 않습니다.
다음을 참고하면서 퍼즈드라를 만들었습니다.
아무래도 사양은 그렇게 제대로 하고 있지 않은 것 같습니다.
관장, 감사합니다! ! !
htps: //같다. 베 / JLQLxrgygk
우선 잘 동작하고 있다고 합니다.
☆블록이 연결할 수 있을 것 같다・・・!
블록을 선택하고 ...
교체하고 연결 블록을 지우십시오! !
소감
int getConnectedBlockCount(int x, int y, int cellType, int count)
이 함수는 연결된 블록의 수를 반환합니다 ...
이것도 함수의 I/F가 바람직하지 않다고 생각합니다.
아니, 좋은가?
인수의 count에 "&"가 붙어 있지 않기 때문에 out이 아님을 명시 할 수 있습니까?
재기 처리를 평소 별로 사용하는 것이 없기 때문에, 공부가 되었습니다!
코드
모처럼이므로 코드를 게시합니다.
자유롭게 시험해 주세요.
정말은 코멘트라든지 네이밍이라도 조금 생각해, 초학자쪽을 알도록(듯이) 하고 싶습니다만・・・
변함없이 부적절한 코딩이 있기 때문에, 잠깐 수정해 가려고 생각합니다.
회귀 테스트하지 않는 아칸으로! ! !
※코드 리뷰 코멘트 받을 수 있으면 다행입니다
#include <iostream>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
static const int FIELD_WIDTH = 8;
static const int FIELD_HEIGHT = 8;
static const int BLOCK_TYPE_MAX = 7;
enum
{
CELL_TYPE_NONE,
CELL_TYPE_BLOCK0,
CELL_TYPE_BLOCK1,
CELL_TYPE_BLOCK2,
CELL_TYPE_BLOCK3,
CELL_TYPE_BLOCK4,
CELL_TYPE_BLOCK5,
CELL_TYPE_BLOCK6,
CELL_TYPE_MAX
};
char cellsAA[][2 + 1] =
{
"・",
"〇",
"△",
"□",
"●",
"▲",
"■",
"☆"
};
int cells[FIELD_WIDTH][FIELD_HEIGHT];
bool checked[FIELD_WIDTH][FIELD_HEIGHT];
int cursorX;
int cursorY;
// -1は、ブロックが選択されていない状態.
int selectedX = -1;
int selectedY = -1;
bool isLocked = true;
unsigned int totalScore;
int getConnectedBlockCount(int x, int y, int cellType, int count);
void eraseConnectedBlocks(int x, int y, int cellType);
void eraseConnectedBlocksAll();
void display();
int main()
{
srand(static_cast<unsigned int>(time(NULL)));
// ボード上にブロックをランダムに配置する.
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
cells[x][y] = CELL_TYPE_BLOCK0 + rand() % BLOCK_TYPE_MAX;
}
}
time_t t = time(NULL);
while (1)
{
if (t < time(NULL))
{
t = time(NULL);
if (true == isLocked)
{
isLocked = false;
// 指定位置のブロックが空であるか判定する.
for (int y = FIELD_HEIGHT - 2; y >= 0; --y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
// 指定位置のブロックが空でなく、その1つ下のブロックが空である場合、指定位置のブロックを落下させる.
if ((CELL_TYPE_NONE != cells[x][y]) && (CELL_TYPE_NONE == cells[x][y + 1]))
{
cells[x][y + 1] = cells[x][y];
cells[x][y] = CELL_TYPE_NONE;
isLocked = true;
}
}
}
// 上からブロックを出現させる.
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if (CELL_TYPE_NONE == cells[x][0])
{
cells[x][0] = CELL_TYPE_BLOCK0 + rand() % BLOCK_TYPE_MAX;
isLocked = true;
}
}
if (false == isLocked)
{
eraseConnectedBlocksAll();
}
}
display();
}
if (_kbhit())
{
if (false == isLocked)
{
switch (_getch())
{
case 'w':
--cursorY;
break;
case 's':
++cursorY;
break;
case 'a':
--cursorX;
break;
case 'd':
++cursorX;
break;
default:
if ((selectedX < 0) && (selectedY < 0))
{
selectedX = cursorX;
selectedY = cursorY;
}
else if ((selectedX < FIELD_WIDTH) && (selectedY < FIELD_HEIGHT))
{
// 選択したブロックとカーソルのブロックとの距離.
int distance = abs(selectedX - cursorX) + abs(selectedY - cursorY);
// 同じブロックを選択すると、選択をキャンセルする.
if (0 == distance)
{
selectedX = -1;
selectedY = -1;
}
// 隣接するブロック同士しか入れ替えできない.
else if (1 == distance)
{
int tmp = cells[selectedX][selectedY];
cells[selectedX][selectedY] = cells[cursorX][cursorY];
cells[cursorX][cursorY] = tmp;
eraseConnectedBlocksAll();
selectedX = -1;
selectedY = -1;
isLocked = true;
}
else
{
std::cout << "\a";
}
}
else
{
std::cout << "\a";
std::cout << "Error!" << std::endl;
}
break;
}
display();
}
}
}
return 0;
}
int getConnectedBlockCount(int x, int y, int cellType, int count)
{
if ((x < 0) || (x >= FIELD_WIDTH) || (y < 0) || (y >= FIELD_HEIGHT)
|| (true == checked[x][y])
|| (CELL_TYPE_NONE == cells[x][y])
|| (cellType != cells[x][y]))
{
return count;
}
++count;
checked[x][y] = true;
// 上.
count = getConnectedBlockCount(x, y - 1, cellType, count);
// 下.
count = getConnectedBlockCount(x, y + 1, cellType, count);
// 左.
count = getConnectedBlockCount(x - 1, y, cellType, count);
// 右.
count = getConnectedBlockCount(x + 1, y, cellType, count);
return count;
}
void eraseConnectedBlocks(int x, int y, int cellType)
{
if ((x < 0) || (x >= FIELD_WIDTH) || (y < 0) || (y >= FIELD_HEIGHT)
|| (CELL_TYPE_NONE == cells[x][y])
|| (cellType != cells[x][y]))
{
return;
}
cells[x][y] = CELL_TYPE_NONE;
++totalScore;
// 上.
eraseConnectedBlocks(x, y - 1, cellType);
// 下.
eraseConnectedBlocks(x, y + 1, cellType);
// 左.
eraseConnectedBlocks(x - 1, y, cellType);
// 右.
eraseConnectedBlocks(x + 1, y, cellType);
}
void eraseConnectedBlocksAll()
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
checked[x][y] = false;
}
}
for (int x = 0; x < FIELD_WIDTH; ++x)
{
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
if (getConnectedBlockCount(x, y, cells[x][y], 0) >= 3)
{
eraseConnectedBlocks(x, y, cells[x][y]);
isLocked = true;
}
}
}
}
void display()
{
system("cls");
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if ((cursorX == x) && (cursorY == y) && (false == isLocked))
{
std::cout << "◎";
}
else
{
std::cout << cellsAA[cells[x][y]];
}
}
if (selectedY == y)
{
std::cout << "←";
}
std::cout << std::endl;
}
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if (selectedX == x)
{
std::cout << "↑";
}
else
{
std::cout << " ";
}
}
std::cout << std::endl;
std::cout << "totalScore = " << totalScore;
}
Reference
이 문제에 관하여(게임 프로그래밍 : C++에서 퍼즈 드라를 만들어 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Chomolungma/items/8b25dd21ad3e014b69a7
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
int getConnectedBlockCount(int x, int y, int cellType, int count)
이 함수는 연결된 블록의 수를 반환합니다 ...
이것도 함수의 I/F가 바람직하지 않다고 생각합니다.
아니, 좋은가?
인수의 count에 "&"가 붙어 있지 않기 때문에 out이 아님을 명시 할 수 있습니까?
재기 처리를 평소 별로 사용하는 것이 없기 때문에, 공부가 되었습니다!
코드
모처럼이므로 코드를 게시합니다.
자유롭게 시험해 주세요.
정말은 코멘트라든지 네이밍이라도 조금 생각해, 초학자쪽을 알도록(듯이) 하고 싶습니다만・・・
변함없이 부적절한 코딩이 있기 때문에, 잠깐 수정해 가려고 생각합니다.
회귀 테스트하지 않는 아칸으로! ! !
※코드 리뷰 코멘트 받을 수 있으면 다행입니다
#include <iostream>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
static const int FIELD_WIDTH = 8;
static const int FIELD_HEIGHT = 8;
static const int BLOCK_TYPE_MAX = 7;
enum
{
CELL_TYPE_NONE,
CELL_TYPE_BLOCK0,
CELL_TYPE_BLOCK1,
CELL_TYPE_BLOCK2,
CELL_TYPE_BLOCK3,
CELL_TYPE_BLOCK4,
CELL_TYPE_BLOCK5,
CELL_TYPE_BLOCK6,
CELL_TYPE_MAX
};
char cellsAA[][2 + 1] =
{
"・",
"〇",
"△",
"□",
"●",
"▲",
"■",
"☆"
};
int cells[FIELD_WIDTH][FIELD_HEIGHT];
bool checked[FIELD_WIDTH][FIELD_HEIGHT];
int cursorX;
int cursorY;
// -1は、ブロックが選択されていない状態.
int selectedX = -1;
int selectedY = -1;
bool isLocked = true;
unsigned int totalScore;
int getConnectedBlockCount(int x, int y, int cellType, int count);
void eraseConnectedBlocks(int x, int y, int cellType);
void eraseConnectedBlocksAll();
void display();
int main()
{
srand(static_cast<unsigned int>(time(NULL)));
// ボード上にブロックをランダムに配置する.
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
cells[x][y] = CELL_TYPE_BLOCK0 + rand() % BLOCK_TYPE_MAX;
}
}
time_t t = time(NULL);
while (1)
{
if (t < time(NULL))
{
t = time(NULL);
if (true == isLocked)
{
isLocked = false;
// 指定位置のブロックが空であるか判定する.
for (int y = FIELD_HEIGHT - 2; y >= 0; --y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
// 指定位置のブロックが空でなく、その1つ下のブロックが空である場合、指定位置のブロックを落下させる.
if ((CELL_TYPE_NONE != cells[x][y]) && (CELL_TYPE_NONE == cells[x][y + 1]))
{
cells[x][y + 1] = cells[x][y];
cells[x][y] = CELL_TYPE_NONE;
isLocked = true;
}
}
}
// 上からブロックを出現させる.
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if (CELL_TYPE_NONE == cells[x][0])
{
cells[x][0] = CELL_TYPE_BLOCK0 + rand() % BLOCK_TYPE_MAX;
isLocked = true;
}
}
if (false == isLocked)
{
eraseConnectedBlocksAll();
}
}
display();
}
if (_kbhit())
{
if (false == isLocked)
{
switch (_getch())
{
case 'w':
--cursorY;
break;
case 's':
++cursorY;
break;
case 'a':
--cursorX;
break;
case 'd':
++cursorX;
break;
default:
if ((selectedX < 0) && (selectedY < 0))
{
selectedX = cursorX;
selectedY = cursorY;
}
else if ((selectedX < FIELD_WIDTH) && (selectedY < FIELD_HEIGHT))
{
// 選択したブロックとカーソルのブロックとの距離.
int distance = abs(selectedX - cursorX) + abs(selectedY - cursorY);
// 同じブロックを選択すると、選択をキャンセルする.
if (0 == distance)
{
selectedX = -1;
selectedY = -1;
}
// 隣接するブロック同士しか入れ替えできない.
else if (1 == distance)
{
int tmp = cells[selectedX][selectedY];
cells[selectedX][selectedY] = cells[cursorX][cursorY];
cells[cursorX][cursorY] = tmp;
eraseConnectedBlocksAll();
selectedX = -1;
selectedY = -1;
isLocked = true;
}
else
{
std::cout << "\a";
}
}
else
{
std::cout << "\a";
std::cout << "Error!" << std::endl;
}
break;
}
display();
}
}
}
return 0;
}
int getConnectedBlockCount(int x, int y, int cellType, int count)
{
if ((x < 0) || (x >= FIELD_WIDTH) || (y < 0) || (y >= FIELD_HEIGHT)
|| (true == checked[x][y])
|| (CELL_TYPE_NONE == cells[x][y])
|| (cellType != cells[x][y]))
{
return count;
}
++count;
checked[x][y] = true;
// 上.
count = getConnectedBlockCount(x, y - 1, cellType, count);
// 下.
count = getConnectedBlockCount(x, y + 1, cellType, count);
// 左.
count = getConnectedBlockCount(x - 1, y, cellType, count);
// 右.
count = getConnectedBlockCount(x + 1, y, cellType, count);
return count;
}
void eraseConnectedBlocks(int x, int y, int cellType)
{
if ((x < 0) || (x >= FIELD_WIDTH) || (y < 0) || (y >= FIELD_HEIGHT)
|| (CELL_TYPE_NONE == cells[x][y])
|| (cellType != cells[x][y]))
{
return;
}
cells[x][y] = CELL_TYPE_NONE;
++totalScore;
// 上.
eraseConnectedBlocks(x, y - 1, cellType);
// 下.
eraseConnectedBlocks(x, y + 1, cellType);
// 左.
eraseConnectedBlocks(x - 1, y, cellType);
// 右.
eraseConnectedBlocks(x + 1, y, cellType);
}
void eraseConnectedBlocksAll()
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
checked[x][y] = false;
}
}
for (int x = 0; x < FIELD_WIDTH; ++x)
{
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
if (getConnectedBlockCount(x, y, cells[x][y], 0) >= 3)
{
eraseConnectedBlocks(x, y, cells[x][y]);
isLocked = true;
}
}
}
}
void display()
{
system("cls");
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if ((cursorX == x) && (cursorY == y) && (false == isLocked))
{
std::cout << "◎";
}
else
{
std::cout << cellsAA[cells[x][y]];
}
}
if (selectedY == y)
{
std::cout << "←";
}
std::cout << std::endl;
}
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if (selectedX == x)
{
std::cout << "↑";
}
else
{
std::cout << " ";
}
}
std::cout << std::endl;
std::cout << "totalScore = " << totalScore;
}
Reference
이 문제에 관하여(게임 프로그래밍 : C++에서 퍼즈 드라를 만들어 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Chomolungma/items/8b25dd21ad3e014b69a7
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
#include <iostream>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
static const int FIELD_WIDTH = 8;
static const int FIELD_HEIGHT = 8;
static const int BLOCK_TYPE_MAX = 7;
enum
{
CELL_TYPE_NONE,
CELL_TYPE_BLOCK0,
CELL_TYPE_BLOCK1,
CELL_TYPE_BLOCK2,
CELL_TYPE_BLOCK3,
CELL_TYPE_BLOCK4,
CELL_TYPE_BLOCK5,
CELL_TYPE_BLOCK6,
CELL_TYPE_MAX
};
char cellsAA[][2 + 1] =
{
"・",
"〇",
"△",
"□",
"●",
"▲",
"■",
"☆"
};
int cells[FIELD_WIDTH][FIELD_HEIGHT];
bool checked[FIELD_WIDTH][FIELD_HEIGHT];
int cursorX;
int cursorY;
// -1は、ブロックが選択されていない状態.
int selectedX = -1;
int selectedY = -1;
bool isLocked = true;
unsigned int totalScore;
int getConnectedBlockCount(int x, int y, int cellType, int count);
void eraseConnectedBlocks(int x, int y, int cellType);
void eraseConnectedBlocksAll();
void display();
int main()
{
srand(static_cast<unsigned int>(time(NULL)));
// ボード上にブロックをランダムに配置する.
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
cells[x][y] = CELL_TYPE_BLOCK0 + rand() % BLOCK_TYPE_MAX;
}
}
time_t t = time(NULL);
while (1)
{
if (t < time(NULL))
{
t = time(NULL);
if (true == isLocked)
{
isLocked = false;
// 指定位置のブロックが空であるか判定する.
for (int y = FIELD_HEIGHT - 2; y >= 0; --y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
// 指定位置のブロックが空でなく、その1つ下のブロックが空である場合、指定位置のブロックを落下させる.
if ((CELL_TYPE_NONE != cells[x][y]) && (CELL_TYPE_NONE == cells[x][y + 1]))
{
cells[x][y + 1] = cells[x][y];
cells[x][y] = CELL_TYPE_NONE;
isLocked = true;
}
}
}
// 上からブロックを出現させる.
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if (CELL_TYPE_NONE == cells[x][0])
{
cells[x][0] = CELL_TYPE_BLOCK0 + rand() % BLOCK_TYPE_MAX;
isLocked = true;
}
}
if (false == isLocked)
{
eraseConnectedBlocksAll();
}
}
display();
}
if (_kbhit())
{
if (false == isLocked)
{
switch (_getch())
{
case 'w':
--cursorY;
break;
case 's':
++cursorY;
break;
case 'a':
--cursorX;
break;
case 'd':
++cursorX;
break;
default:
if ((selectedX < 0) && (selectedY < 0))
{
selectedX = cursorX;
selectedY = cursorY;
}
else if ((selectedX < FIELD_WIDTH) && (selectedY < FIELD_HEIGHT))
{
// 選択したブロックとカーソルのブロックとの距離.
int distance = abs(selectedX - cursorX) + abs(selectedY - cursorY);
// 同じブロックを選択すると、選択をキャンセルする.
if (0 == distance)
{
selectedX = -1;
selectedY = -1;
}
// 隣接するブロック同士しか入れ替えできない.
else if (1 == distance)
{
int tmp = cells[selectedX][selectedY];
cells[selectedX][selectedY] = cells[cursorX][cursorY];
cells[cursorX][cursorY] = tmp;
eraseConnectedBlocksAll();
selectedX = -1;
selectedY = -1;
isLocked = true;
}
else
{
std::cout << "\a";
}
}
else
{
std::cout << "\a";
std::cout << "Error!" << std::endl;
}
break;
}
display();
}
}
}
return 0;
}
int getConnectedBlockCount(int x, int y, int cellType, int count)
{
if ((x < 0) || (x >= FIELD_WIDTH) || (y < 0) || (y >= FIELD_HEIGHT)
|| (true == checked[x][y])
|| (CELL_TYPE_NONE == cells[x][y])
|| (cellType != cells[x][y]))
{
return count;
}
++count;
checked[x][y] = true;
// 上.
count = getConnectedBlockCount(x, y - 1, cellType, count);
// 下.
count = getConnectedBlockCount(x, y + 1, cellType, count);
// 左.
count = getConnectedBlockCount(x - 1, y, cellType, count);
// 右.
count = getConnectedBlockCount(x + 1, y, cellType, count);
return count;
}
void eraseConnectedBlocks(int x, int y, int cellType)
{
if ((x < 0) || (x >= FIELD_WIDTH) || (y < 0) || (y >= FIELD_HEIGHT)
|| (CELL_TYPE_NONE == cells[x][y])
|| (cellType != cells[x][y]))
{
return;
}
cells[x][y] = CELL_TYPE_NONE;
++totalScore;
// 上.
eraseConnectedBlocks(x, y - 1, cellType);
// 下.
eraseConnectedBlocks(x, y + 1, cellType);
// 左.
eraseConnectedBlocks(x - 1, y, cellType);
// 右.
eraseConnectedBlocks(x + 1, y, cellType);
}
void eraseConnectedBlocksAll()
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
checked[x][y] = false;
}
}
for (int x = 0; x < FIELD_WIDTH; ++x)
{
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
if (getConnectedBlockCount(x, y, cells[x][y], 0) >= 3)
{
eraseConnectedBlocks(x, y, cells[x][y]);
isLocked = true;
}
}
}
}
void display()
{
system("cls");
for (int y = 0; y < FIELD_HEIGHT; ++y)
{
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if ((cursorX == x) && (cursorY == y) && (false == isLocked))
{
std::cout << "◎";
}
else
{
std::cout << cellsAA[cells[x][y]];
}
}
if (selectedY == y)
{
std::cout << "←";
}
std::cout << std::endl;
}
for (int x = 0; x < FIELD_WIDTH; ++x)
{
if (selectedX == x)
{
std::cout << "↑";
}
else
{
std::cout << " ";
}
}
std::cout << std::endl;
std::cout << "totalScore = " << totalScore;
}
Reference
이 문제에 관하여(게임 프로그래밍 : C++에서 퍼즈 드라를 만들어 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Chomolungma/items/8b25dd21ad3e014b69a7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)