I took some days to code 2048 game. And now I made most of the functions but one, testing whether the game is over. To code this game, my idea is to merge the same numbers first with the function up(down, left or right)_merge and make all the numbers go to the arrow direction that user presses with the function all_go_up(down, left or right). And then add a new number with the add_new_number function.
Here are some piece of those code I mentioned above:
void up_merge()
{
for(int i = 1; i < 4; i++) {
for(int j = 0; j < 4; j++) {
if(grid[i][j] > 0 && grid[i - 1][j] == grid[i][j]) {
while(grid[i - 1][j] == grid[i][j]) {
grid[i - 1][j] *= 2;
grid[i][j] = 0;
}
}
else if(grid[i][j] > 0 && grid[i - 1][j] == 0 && grid[i - 2][j] == grid[i][j]) {
while(grid[i - 2][j] == grid[i][j]) {
grid[i - 2][j] *= 2;
grid[i][j] = 0;
}
}
else if(grid[i][j] > 0 && grid[i - 1][j] == 0 && grid[i - 2][j] == 0 && grid[i - 3][j] == grid[i][j]) {
while(grid[i - 3][j] == grid[i][j]) {
grid[i - 3][j] *= 2;
grid[i][j] = 0;
}
}
}
}
}
void all_go_up()
{
for(int i = 3; i > 0; i--) {
for(int j = 0; j < 4; j++) {
if(grid[i][j] > 0 && grid[i - 1][j] == 0) {
grid[i - 1][j] = grid[i][j];
grid[i][j] = 0;
}
for(int k = 3; k > 0; k--) {
if(grid[k][j] > 0 && grid[k - 1][j] == 0) {
grid[k - 1][j] = grid[k][j];
grid[k][j] = 0;
}
}
}
}
}
bool add_new_number(int num)
{
int n = rand() % 2 + 1;
int newnumber = 1 << n;
int r, c;
switch(num) {
case 1: //up
r = rand() % 2 + 2;
c = rand() % 4;
break;
case 2: //down
r = rand() % 2;
c = rand() % 4;
break;
case 3: //left
r = rand() % 4;
c = rand() % 2 + 2;
break;
case 4: //right
r = rand() % 4;
c = rand() % 2;
break;
}
do {
if(check_empty() == 1) {
if(grid[r][c] == 0) {
grid[r][c] = newnumber;
return false;
}
if(grid[r][c] != 0) {
switch(num) {
case 1: //up
r = rand() % 2 + 2;
c = rand() % 4;
break;
case 2: //down
r = rand() % 2;
c = rand() % 4;
break;
case 3: //left
r = rand() % 4;
c = rand() % 2 + 2;
break;
case 4: //right
r = rand() % 4;
c = rand() % 2;
break;
}
}
}
else {
return false;
}
} while(true);
}
I have some other functions to check whether the grid is full and so on. I also tried use some while() and for() to do this, too. But I do not know where I get wrong to code the function to test whether the game is over.
I hope I express my problem well. Hoping to get some suggestions to code the test_fail function without changing too much of my code. Thanks.
With all the respect, your code looks totally unreadable. Consider functional approach where you compose few smaller function to break down more complex problem. I am going to demonstrate this in Typescript but it would be very similar in C++. In this way the code is I believe self-explanatory.
type Board = number[][]
function isGameOver(board: Board) {
if (hasEmptySpace(board)) return false
return checkHorizontalGameOver(board) && checkVerticalGameOver(board)
}
function hasEmptySpace(board: Board) {
for (let r = 0; r < NUM_ROWS; r++) {
for (let c = 0; c < NUM_COLS; c++) {
if (board[r][c] === 0) return true
}
}
return false
}
function checkHorizontalGameOver(board: Board) {
for (let i = 0; i < NUM_ROWS; i++) {
for (let j = 0; j < NUM_COLS - 1; j++) {
if (board[i][j] === board[i][j + 1]) return false
}
}
return true
}
function checkVerticalGameOver(board: Board) {
for (let i = 0; i < NUM_ROWS - 1; i++) {
for (let j = 0; j < NUM_COLS; j++) {
if (board[i][j] === board[i + 1][j]) return false
}
}
return true
}
I understand it's 5 years ago as I am reading now and your skills in programming are far far better, but still - I will post it here for people who might come across this so it can possibly help them.
Related
I have just successfully linked the SFML library to my Visual Studio 2019. I am trying to run a simple C++ game Minesweeper. It compiles, gives no error message, but gives weird unexpected results in the runtime window. It says failed to load images. Please help. This is a pic of the error message, and see code for game below.
Failed to load images pic
#include <SFML/Graphics.hpp>
#include <time.h>
using namespace sf;
int main()
{
srand(time(0));
RenderWindow app(VideoMode(400, 400), "Minesweeper!");
int w = 32;
int grid[12][12];
int sgrid[12][12]; //for showing
Texture t;
t.loadFromFile("images/tiles.jpg");
Sprite s(t);
for (int i = 1; i <= 10; i++)
for (int j = 1; j <= 10; j++)
{
sgrid[i][j] = 10;
if (rand() % 5 == 0) grid[i][j] = 9;
else grid[i][j] = 0;
}
for (int i = 1; i <= 10; i++)
for (int j = 1; j <= 10; j++)
{
int n = 0;
if (grid[i][j] == 9) continue;
if (grid[i + 1][j] == 9) n++;
if (grid[i][j + 1] == 9) n++;
if (grid[i - 1][j] == 9) n++;
if (grid[i][j - 1] == 9) n++;
if (grid[i + 1][j + 1] == 9) n++;
if (grid[i - 1][j - 1] == 9) n++;
if (grid[i - 1][j + 1] == 9) n++;
if (grid[i + 1][j - 1] == 9) n++;
grid[i][j] = n;
}
while (app.isOpen())
{
Vector2i pos = Mouse::getPosition(app);
int x = pos.x / w;
int y = pos.y / w;
Event e;
while (app.pollEvent(e))
{
if (e.type == Event::Closed)
app.close();
if (e.type == Event::MouseButtonPressed)
if (e.key.code == Mouse::Left) sgrid[x][y] = grid[x][y];
else if (e.key.code == Mouse::Right) sgrid[x][y] = 11;
}
app.clear(Color::White);
for (int i = 1; i <= 10; i++)
for (int j = 1; j <= 10; j++)
{
if (sgrid[x][y] == 9) sgrid[i][j] = grid[i][j];
s.setTextureRect(IntRect(sgrid[i][j] * w, 0, w, w));
s.setPosition(i * w, j * w);
app.draw(s);
}
app.display();
}
return 0;
}
Hello I have been attempting to add a scoring scheme which is 11 for internal gaps, 8 for terminal gaps on the 5 prime end, 7 for gaps on the 3' end, 4 for mismatches, 0 for matches. Currently the code only accounts for internal gap (= 11), mismatches(= 4) and matches (=0) but not for terminal gaps. Im fairly new to coding so I apologise in advance if my code is messy, any guidance is appreciated. I should be getting a score of 275.
The two sequences I used are included in the code.
#include <iostream>
#include <fstream>
#include <bits/stdc++.h>
using namespace std;
void getscore(string x, string y, int pxy, int pgap)
{
int i, j;
int m = x.length();
int n = y.length();
int dp[n+m+1][n+m+1] = {0};
for (i = 0; i <= (n+m); i++)
{
dp[i][0] = i * pgap;
dp[0][i] = i * pgap;
}
for (i = 1; i <= m; i++)
{
for (j = 1; j <= n; j++)
{
if (x[i - 1] == y[j - 1])
{
dp[i][j] = dp[i - 1][j - 1];
}
else
{
dp[i][j] = min({dp[i - 1][j - 1] + pxy ,
dp[i - 1][j] + pgap ,
dp[i][j - 1] + pgap });
}
}
}
int l = n + m;
i = m; j = n;
int xpos = l;
int ypos = l;
int xans[l+1], yans[l+1];
while ( !(i == 0 || j == 0))
{
if (x[i - 1] == y[j - 1])
{
xans[xpos--] = (int)x[i - 1];
yans[ypos--] = (int)y[j - 1];
i--; j--;
}
else if (dp[i - 1][j - 1] + pxy == dp[i][j])
{
xans[xpos--] = (int)x[i - 1];
yans[ypos--] = (int)y[j - 1];
i--; j--;
}
else if (dp[i - 1][j] + pgap == dp[i][j])
{
xans[xpos--] = (int)x[i - 1];
yans[ypos--] = (int)'_';
i--;
}
else if (dp[i][j - 1] + pgap == dp[i][j])
{
xans[xpos--] = (int)'_';
yans[ypos--] = (int)y[j - 1];
j--;
}
}
while (xpos > 0)
{
if (i > 0) xans[xpos--] = (int)x[--i];
else xans[xpos--] = (int)'_';
}
while (ypos > 0)
{
if (j > 0) yans[ypos--] = (int)y[--j];
else yans[ypos--] = (int)'_';
}
int id = 1;
for (i = l; i >= 1; i--)
{
if ((char)yans[i] == '_' && (char)xans[i] == '_')
{
id = i + 1;
break;
}
}
// Printing the final answer
cout << "Optimal score = ";
cout << dp[m][n] << "\n";
cout << "Optimal alignment :\n";
for (i = id; i <= l; i++)
{
cout<<(char)xans[i];
}
cout << "\n";
for (i = id; i <= l; i++)
{
cout << (char)yans[i];
}
return;
}
int main(){
string geneA = "TCTGGTGTCCTAGGCGTAGAGGAACCACACCAATCCATCCCGAACTCTGGTGGTTAAACTCTACTGCGGTGACGATACT ";
string geneB = "TGGTGCGGTCATACCAGCGCTAATGCACCGGATCCCATCAGAACTCCGCAGTTAAGCGCGCTTGGGCCAGAACAGTACTGGGATGGGTGTCC ";
int misMatchPenalty = 4;
int gapPenalty = 11;
int tPenalty=7;
int fPenalty=8;
getscore(geneA, geneB,
misMatchPenalty, gapPenalty);
return 0;
}
I'm making a simple maze program that generates a maze. Currently I was working on making one and only solution to a maze, when I stumbled onto something weird. When I debug this code I see that VS is just skipping my if statements here:
for (i = 0; i <= (col * row) / 200; i++)
{
solution[se[0]][se[1]] = 1;
if (lab[se[0] + 1][se[1]]) se[0] + 1;
else if (lab[se[0]][se[1] + 1]) se[1] + 1;
else if (lab[se[0] - 1][se[1]]) se[0] - 1;
else if (lab[se[0]][se[1] - 1]) se[1] - 1;
solution[se[2]][se[3]] = 1;
if (lab[se[2] - 1][se[3]]) se[2] - 1;
else if (lab[se[2]][se[3] - 1]) se[3] - 1;
else if (lab[se[2] + 1][se[3]]) se[2] + 1;
else if (lab[se[2]][se[3] + 1]) se[3] + 1;
}
I hope it's not a duplicate, but I have no slightest idea what's the problem here, so it could be one.
Here's the full code if someone wants to replicate the problem:
#include <stdio.h>
#include <iostream>
#include <Windows.h>
#include <string>
CONSOLE_SCREEN_BUFFER_INFO csbi;
int **lab, **solution;
int col, row, i, j;
int main() {
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
col = csbi.srWindow.Right - csbi.srWindow.Left; row = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; i = 0; j = 0;
lab = new int* [row];
for (i = 0; i < row; ++i)
lab[i] = new int[col];
solution = new int* [row];
for (i = 0; i < row; ++i)
solution[i] = new int[col];
for (i = 0; i < row; i++) { // Build basic maze
for (j = 0; j < col; j++) {
if (i == 0) lab[i][j] = 0;
else if (i == j == 1) lab[i][j] = 1;
else if (i == 1 && j == col - 1) lab[i][j] = 1;
else if (i == row - 1) lab[i][j] = 0;
else if (j == 0) lab[i][j] = 0;
else if (j == col - 1) lab[i][j] = 0;
else {
if (lab[i - 1][j] == 0) lab[i][j] = rand() % 2;
else {
if (lab[i - 1][j - 1] + lab[i - 1][j + 1] + lab[i - 2][j] <= 1) lab[i][j] = 1;
else {
lab[i][j] = rand() % 2;
}
}
}
}
}
int se[4] = { 1,1,1,col - 1 };
for (i = 0; i <= (col * row) / 200; i++) // Generate a solution
{
solution[se[0]][se[1]] = 1;
if (lab[se[0] + 1][se[1]]) se[0] + 1;
else if (lab[se[0]][se[1] + 1]) se[1] + 1;
else if (lab[se[0] - 1][se[1]]) se[0] - 1;
else if (lab[se[0]][se[1] - 1]) se[1] - 1;
solution[se[2]][se[3]] = 1;
if (lab[se[2] - 1][se[3]]) se[2] - 1;
else if (lab[se[2]][se[3] - 1]) se[3] - 1;
else if (lab[se[2] + 1][se[3]]) se[2] + 1;
else if (lab[se[2]][se[3] + 1]) se[3] + 1;
}
while (se[0] != se[2] || se[1] != se[3])
{
if (se[0] < se[2])
{
if (lab[se[2] - 1][se[3]]) se[2] - 1;
if (lab[se[0] + 1][se[1]]) se[0] + 1;
}
if (se[1] < se[3])
{
if (lab[se[2]][se[3] - 1]) se[3] + 1;
if (lab[se[0]][se[1] + 1]) se[1] + 1;
}
solution[se[0]][se[1]] = 1;
solution[se[2]][se[3]] = 1;
}
std::string out;
for (i = 0; i < row; i++) { // Print maze
for (j = 0; j < col; j++) {
if (solution[i][j]==1) out.append("#");
else if (!lab[i][j]) out.append("#");
else out.append(" ");;
}
std::cout << out << '\n';
out="";
}
system("pause");
for (i = 0; i < row; ++i) delete[] lab[i];
delete[] lab;
}
I'm sorry, this code is a mess, because it's still work in progress.
BTW I'm using VS 2019, didn't try it in another compiler yet. Is it really a compiler's fault?
The reason why the compiler sees fit to 'skip' the if blocks is because there is no code in them that has any effect!
For example, in the statement:
if (lab[se[0] + 1][se[1]]) se[0] + 1;
when the condition in the test is "true" what happens? The statement se[0] + 1 doesn't actually modify anything - it is simply an expression that has the given value.
What you probably want is to add 1 to se[0], so you need this:
if (lab[se[0] + 1][se[1]]) se[0] += 1;
and similarly for the other if and else if lines. (Note the added = character!)
this code attempts to solve the 4 queens problem, placing 4 queens on a 4*4 chessboard without any of them being able to capture eachother
#include <iostream>
using namespace std;
int Place(int Chess[][4], int collumn, int i);
bool Check(int Chess[][4], int collumn, int i);
int findrow(int Chess[][4], int collumn);
const int size = 3;
int main()
{
int Chess[4][4];
int collumn;
int i = 0;
collumn = 0;
for(int s = 0; s < 4; s++)
{
for(int j = 0; j < 4; j ++)
{
Chess[s][j] = 0;
}
}
//Chess[0][0] = 1;
//Chess[3][3] = 1;
//if(Check(Chess, 3, 3) == false)
Place(Chess, collumn, i);
for(int z = 0; z < 4; z++)
{
for(int a = 0; a < 4; a++)
{
if(Chess[z][a] == 1)
cout<<"Row: "<<z<<"Collumn: "<<a<<"."<<endl;
}
cout<<endl;
}
system("pause");
return 0;
}
int Place(int Chess[][4], int collumn, int i)
{
if(collumn > size)
return 0;
while(i <= size)
{
if(Check(Chess, collumn, i) == true)
{
//cout<<"hi"<<endl;
Chess[collumn][i] = 1;
return(Place(Chess, (collumn + 1), i));
}
i ++;
}
if(i>= size)
{
//cout<<"hilo"<<endl;
return Place(Chess, collumn-1, findrow(Chess, collumn-1));
}
}
bool Check(int Chess[][4], int collumn, int i)//checks to see if it can be captured
{// very inneficitnt
int x = collumn;// this is so we can now work in terms of x and y
int y = i;
bool found = true;
// checks all the diagonal captures
if(Chess[x -1 ][y -1]== 1&& x>=1 && y >=1 )
found = false;
if(Chess[x -2 ][y - 2]== 1&& x>=2 && y>=2 )
found = false;
if(Chess[x - 3][y - 3]== 1 && x>=3 && y>=3 )
found = false;
if(Chess[x + 1][y - 1] == 1&& x<=2 && y>=1 )
found = false;
if(Chess[x + 2][y -2] == 1&& x<=1 && y>=2)
found = false;
if(Chess[x + 3][y - 3] == 1 && x<=0 && y>=3)
found = false;
if(Chess[x + 1][y + 1] == 1 && x<=2 && y<=2)
found = false;
if(Chess[x + 2][y + 2] == 1&& x<=1 && y<=1)
found = false;
if(Chess[x + 3][y + 3] == 1 && x<=0 && y<=0 )
found = false;
if(Chess[x -1 ][y + 1]== 1 && x>=1 && y<=2 )
found = false;
if(Chess[x - 2][y + 2] == 1&& x>=2 && y<=1 )
found = false;
if(Chess[x - 3][y + 3] == 1&& x>=3 && y<=0)
found = false;
//checks all the horizontal captures. We don't need to check for vertical captures
if(Chess[x + 1][y] == 1 && x<=2)
found = false;
if(Chess[x + 2][y] == 1&& x<=1 )
found = false;
if(Chess[x+3][y] == 1 && x<=0)
found = false;
if(Chess[x -1 ][y] == 1&& x>=1)
found = false;
if(Chess[x-2][y] == 1&& x>=2 )
found = false;
if(Chess[x-3][y] == 1 && x>=3)
found = false;
if(found == false)
return false;
if(found == true)
return true;
}
int findrow(int Chess[][4], int collumn)
{
for(int z = 0; z < 4; z++)
{
if(Chess[collumn][z] == 1)
{
Chess[collumn][z] = 0;
return z;
}
}
}
The first thing I see is a probable out-of-bounds access:
if(Chess[x -1 ][y -1]== 1&& x>=1 && y >=1 )
What if the value of x is 0? You are accessing Chess[-1][y], which is out of bounds. Your if statement does not stop this, even with the x>=1 condition.
The if will first test the Chess[x-1][y-1]==1 condition. If you want this to not happen, place the test for x>=1 before Chess[x-1][y-1]==1.
But even with this, that entire section of code looks suspicious. I wouldn't be surprised if there were more out-of-bounds accesses.
http://uva.onlinejudge.org/external/6/674.html I'm trying to solve that problem. Note, though, that it's not the minimum coin change problem, it asks me for the different number of ways to make N cents using 50, 25, 15, 10, 5 and 1 cent coins. It's fairly straightforward, so I made this function:
int count(int n, int m) // n is the N of the problem, m is the number of coin types and s[] is {1, 5, 10, 25, 50}
{
if (n == 0)
{
return 1;
}
if (n < 0)
{
return 0;
}
if (m < 0 && n >= 1)
{
return 0;
}
return DP[n][m - 1] + DP[n - s[m]][m];
}
Fairly straightforward too is adding Dynamic Programming with memoization:
int count(int n, int m)
{
if (n == 0)
{
return 1;
}
if (n < 0)
{
return 0;
}
if (m < 0 && n >= 1)
{
return 0;
}
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return count(n, m - 1) + count(n - s[m], m);
}
else
{
return DP[n][m - 1] + DP[n - s[m]][m];
}
}
However, none of these is fast enough - I need bottom up Dynamic Programming, but I am having difficulties coding it, even with some help from Algorithmist - http://www.algorithmist.com/index.php/Coin_Change.
void generate()
{
for (i = 0; i < MAX; i++)
{
for (u = 0; u < m; u++)
{
if (i == 0)
{
DP[i][u] = 1;
}
else if (u == 0)
{
DP[i][u] = 0;
}
else if (s[u] > i)
{
DP[i][u] = DP[i][u - 1];
}
else
{
DP[i][u] = DP[i][u - 1] + DP[i - s[u]][u];
}
}
}
}
I get 0 for every result for some reason, here's my full code:
#include <stdio.h>
#include <string.h>
using namespace std;
#define MAX 7490
int s[] = {1, 5, 10, 25, 50}, m = 5, input, DP[MAX][5], i, u;
int count(int n, int m)
{
if (n == 0)
{
return 1;
}
if (n < 0)
{
return 0;
}
if (m < 0 && n >= 1)
{
return 0;
}
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return count(n, m - 1) + count(n - s[m], m);
}
else
{
return DP[n][m - 1] + DP[n - s[m]][m];
}
}
void generate()
{
for (i = 0; i < MAX; i++)
{
for (u = 0; u < m; u++)
{
if (i == 0)
{
DP[i][u] = 1;
}
else if (u == 0)
{
DP[i][u] = 0;
}
else if (s[u] > i)
{
DP[i][u] = DP[i][u - 1];
}
else
{
DP[i][u] = DP[i][u - 1] + DP[i - s[u]][u];
}
}
}
}
int main()
{
memset(DP, -1, sizeof DP);
generate();
while (scanf("%d", &input) != EOF)
{
//printf("%d\n", count(input, 4));
printf("%d\n", DP[input][4]);
}
return 0;
}
You did the mistake here:
else if (u == 0)
{
DP[i][u] = 0;
}
It should be DP[i][u]=1 because you can produce any value i using 1 cent coin in 1 possible way. i.e. to take 5 cent you will take 5 one cent coins which is one way to make 5-cent in total.
-----
Btw, in you 1st approach in count method did you have this:
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return count(n, m - 1) + count(n - s[m], m);
}
Or this:
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return DP[n][m] = count(n, m - 1) + count(n - s[m], m);
}
If you did not memoize an already calculated result then this memoization check if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1) will never work, which might be the cause of your 1st approach to be too slow :-?