Skip to content

Instantly share code, notes, and snippets.

@corlaez
Created June 15, 2025 23:22
Show Gist options
  • Save corlaez/39b74508645b33f399f39c036a1b23d4 to your computer and use it in GitHub Desktop.
Save corlaez/39b74508645b33f399f39c036a1b23d4 to your computer and use it in GitHub Desktop.
Carrera C++ con musica
#include "pch.h"
#include <iostream>
#include <conio.h>
#include <Windows.h>
#include <ctime>
#include <thread>
#include <vector>
using namespace System;
using namespace std;
const int ANCHO = 90; // columnas
const int ALTO = 34; // filas
const int numerocarros = 6;
const int carros_alto = 2;
const int carros_ancho = 14;
const ConsoleColor paleta[numerocarros] =
{
ConsoleColor::Red,
ConsoleColor::Blue,
ConsoleColor::Green,
ConsoleColor::Cyan,
ConsoleColor::Magenta,
ConsoleColor::Yellow
};
ConsoleColor color[numerocarros];
int posX[numerocarros];
int posY[numerocarros];
int vel[numerocarros];
int wins[numerocarros] = { 0 };
bool der[numerocarros];
int limIzq[numerocarros];
int limDer[numerocarros];
int etapa[numerocarros];
const int filaMeta[6] = { 20,22,24,26,28,30 };
const int metaFinalX = 0;
const int paso[6] = { 120000, 130000, 150000, 150000, 180000, 190000 };
/* Bloquea la ejecucion del codigo hasta que detecta que la tecla ha sido presionada */
void esperarTecla(char tecla) {
while (true) {
if (kbhit)
{
if (getch() == tecla)
{
break;
}
}
}
}
/* Bloquea la ejecucion del codigo hasta que detecta que una de las teclas ha sido presionada y retorna su indice */
int esperarTeclas(std::initializer_list<char> teclas) {
while (true) {
if (kbhit)
{
char teclaPresionada = getch();
for (size_t i = 0; i < teclas.size(); ++i) {
if (teclaPresionada == teclas.begin()[i])
{
return i;
}
}
}
}
}
void moverCursor(int x, int y) {
if (x >= 0 && x < ANCHO && y >= 0 && y < ALTO)
Console::SetCursorPosition(x, y);
}
const char* carroDer[numerocarros][carros_alto] = {
{
"_/¯¯¯¯¯¯¯¯\\__",
"\\--O-----O--/"
},
{
"---------- ",
"-@-[O_O]-@-- "
},
{
" #-------->> ",
"--[]--------[]"
},
{
" >>═══════ ",
"¯¯(_)¯¯¯(_)¯¯ "
},
{
" /¯¯¯¯\\___ ",
"/\\(o¯¯o)__/ "
},
{
"_________ ",
"\\(_)---(_)-/ "
}
};
const char* carroIzq[numerocarros][carros_alto] = {
{
"__/¯¯¯¯¯¯¯¯\\_",
"\\--O-----O--/"
},
{
" ----------",
" --@-[O_O]-@-"
},
{
" <<--------# ",
"[]--------[]--"
},
{
" ═══════<< ",
" ¯¯(_)¯¯¯(_)¯¯"
},
{
" ___/¯¯¯¯¯\\ ",
" \\__(o¯¯o)/\\"
},
{
" _________",
" \\-(_)---(_)/"
}
};
void asignarVelocidades()
{
for (int i = 0; i < numerocarros; ++i)
{
int v;
bool repetido;
do {
v = rand() % 6; // ahora 0..5
repetido = false;
for (int j = 0; j < i; j++) {
if (vel[j] == v) { // ¿está tomado?
repetido = true;
break;
}
}
} while (repetido); // repite hasta ser único
vel[i] = v; // guarda velocidad del auto i
}
}
void configurarVentana() {
Console::SetWindowSize(ANCHO, ALTO);
Console::CursorVisible = false; // con esto cambias la ventana ddf
}
void opciones() {
moverCursor(24, 17); cout << "[1] Carrera";
moverCursor(38, 17); cout << "[2] Creditos";
moverCursor(53, 17); cout << "[3] Salir";
}
void nombreJuego() {
moverCursor(10, 5); cout << " ____ _ ____ ____ _____ ____ ___ ____ _ _ _____ ____";
moverCursor(10, 6); cout << "/ ___| / \\ | _ \\ | _ \\| ____/ ___|_ _/ ___| \\ | | ____| _ \\.";
moverCursor(10, 7); cout << "| | / _ \\ | |_) | | | | | _ |\\___\\ | | | _| \\| | _| | |_) |";
moverCursor(10, 8); cout << "| |___/ ___ \\| _ < | |_| | |___ ___) | | |_| | |\\ | |___| _ <";
moverCursor(10, 9); cout << "\\____/_/ \\_\\_| \\_\\ |____/|_____|____/___\\____|_| \\_|_____|_| \\_\\.";
}
void creditos() {
Console::SetCursorPosition(10, 10);
cout << "Hecho por Andres Espejo, Piero Burgos y Fabio Silva";
}
void asignarColores()
{
for (int i = 0; i < numerocarros; i++) {
int paletacarros;
bool repetido;
do {
paletacarros = rand() % 6; // elige un color de 0..5
repetido = false;
for (int j = 0; j < i; j++) { // ¿ya se usó?
if (color[j] == paleta[paletacarros]) {
repetido = true;
break;
}
}
} while (repetido); // repite hasta que no se repita
color[i] = paleta[paletacarros]; // guarda el color único
}
}
void dibujarAuto(int id, int x, int y, bool derecha)
{
Console::ForegroundColor = color[id]; // color único
const char** linea = derecha ? carroDer[id] : carroIzq[id];
for (int r = 0; r < carros_alto; ++r) {
moverCursor(x, y + r);
cout << linea[r];
}
Console::ForegroundColor = ConsoleColor::Gray;
}
void colocarAutosInicio() {
/* límites personalizados – ajusta si lo deseas */
int izq[6] = { 1, 16, 30, 1, 16, 31 };
int der[6] = { 50, 63, 72, 50, 63, 72 };
for (int id = 0; id < numerocarros; ++id) {
limIzq[id] = izq[id];
limDer[id] = der[id];
posX[id] = limIzq[id]; // arranca pegado al límite izq.
posY[id] = 2 + (id / 3) * (carros_alto + 2);
der[id] = true;
etapa[id] = 0;
dibujarAuto(id, posX[id], posY[id], true);
}
}
void borrarCarro(int id) {
for (int r = 0; r < carros_alto; r++) {
moverCursor(posX[id], posY[id] + r);
cout << string(carros_ancho, ' ');
}
}
void dibujarmeta(int x, int y) {
char b = 219;
Console::SetCursorPosition(x, y + 20);
cout << " " << b << " " << b << " " << b << endl;
cout << b << " " << b << " " << b << " " << endl;
cout << " " << b << " " << b << " " << b << endl;
cout << b << " " << b << " " << b << " " << endl;
cout << " " << b << " " << b << " " << b << endl;
cout << b << " " << b << " " << b << " " << endl;
cout << " " << b << " " << b << " " << b << endl;
cout << b << " " << b << " " << b << " " << endl;
cout << " " << b << " " << b << " " << b << endl;
cout << b << " " << b << " " << b << " " << endl;
cout << " " << b << " " << b << " " << b << endl;
cout << b << " " << b << " " << b << " " << endl;
cout << " " << b << " " << b << " " << b << endl;
}
void iniciarcarrera() {};
void bucleCarrera() {
int frame = 0;
bool hayGanador = false;
while (!hayGanador) {
for (int id = 0; id < numerocarros; ++id) {
/* Avanza solo cada vel[id] frames */
if (frame % paso[vel[id]] == 0) {
borrarCarro(id);
if (etapa[id] == 0) {
if (posX[id] < limDer[id]) {
++posX[id];
der[id] = true;
}
else {
etapa[id] = 1;
}
}
else if (etapa[id] == 1) {
if (posY[id] < filaMeta[id]) ++posY[id];
else etapa[id] = 2;
der[id] = false;
}
else {
if (posX[id] > metaFinalX) {
--posX[id];
}
else {
wins[id]++; hayGanador = true;
moverCursor(0, ALTO - 2);
cout << "Ganador: Auto #" << id + 1;
}
}
dibujarAuto(id, posX[id], posY[id], der[id]);
}
}
Sleep(0);
++frame;
}
}
void ranking() {};
void dibujarpista(int x, int y) {
char g = 238;
Console::SetCursorPosition(x, y + 10);
cout << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g;
Console::SetCursorPosition(x + 48, y + 10);
cout << "|";
Console::SetCursorPosition(x + 48, y + 11);
cout << "|";
Console::SetCursorPosition(x + 48, y + 12);
cout << "|";
Console::SetCursorPosition(x + 48, y + 13);
cout << "|";
Console::SetCursorPosition(x + 48, y + 14);
cout << "|";
Console::SetCursorPosition(x + 48, y + 15);
cout << "|";
Console::SetCursorPosition(x + 48, y + 16);
cout << "|";
Console::SetCursorPosition(x + 48, y + 17);
cout << "|";
Console::SetCursorPosition(x + 48, y + 18);
cout << "|";
Console::SetCursorPosition(x, y + 19);
cout << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g << g;
}
void simulacion_carrera() {
dibujarpista(0, 0);
dibujarmeta(0, 0);
asignarColores();
asignarVelocidades();
colocarAutosInicio(); // pinta autos y pone límites
bucleCarrera(); // ← ¡ahora sí se mueven!
cout << "\nPulsa una tecla...";
_getch();
}
void inicio() {
Console::Clear();
nombreJuego();
opciones();
int i = esperarTeclas({ '1', '2', '3' });
if (i == 0) {
Console::Clear();
simulacion_carrera();
}
if (i == 1) {
Console::Clear();
creditos();
esperarTecla(27);
inicio();
}
if (i == 2) {
std::exit(0);
}
}
struct NotaMusical {
unsigned int frecuencia_hz;// 0 es un silencio
unsigned int duracion_ms;
};
const std::vector<NotaMusical> melodia = {
// Frase 1: Intro
{622, 75}, // D#5
{0, 25},
{698, 75}, // F5
{0, 25},
{784, 75}, // G5
{0, 25},
{932, 100},// A#5
// Frase 2: Rapidez!
{880, 50}, // A5
{784, 50}, // G5
{698, 50}, // F5
{0, 50},
// Frase 3: Anticipacion
{587, 75}, // D5
{0, 25},
{698, 75}, // F5
{0, 25},
{784, 75}, // G5
{0, 25},
{880, 100},// A5
// Frase 4: Resolucion que nos impulsa a reiniciar
{784, 50}, // G5
{622, 50}, // D#5
{523, 50}, // C5
{0, 100}
};
// Funcion que toca la melodia en bucle (bloquea el thread)
void tocarMelodiaEnBucle() {
while (true) { // Loopea indefinidamente
for (const auto& note : melodia) {
if (note.frecuencia_hz == 0) { // Descanzo
std::this_thread::sleep_for(std::chrono::milliseconds(note.duracion_ms));
}
else { // It's a note
Beep(note.frecuencia_hz, note.duracion_ms);
}
}
}
}
/* ─── Programa principal ─── */
int main() {
// toca musica
std::thread melodiaHilo(tocarMelodiaEnBucle);
melodiaHilo.detach();// no nos importa que este thread se cancele si main se cancela
srand(time(0));
configurarVentana();
Console::Clear();
inicio();
//moverCursor(0, ALTO - 1);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment