2014-10-07 3 views
1

Я работаю над программой, которая должна читаться в файле (каждая строка в файле представляет собой руку из 13 карт) и оценивает каждую руку моста.Оценка моста Руки в C++

В конце я задам свои конкретные вопросы, но поскольку в этой программе есть хороший бит, я собираюсь включить все инструкции, чтобы вы получили представление о том, что требуется.

Вот текстовый файл, который будет читаться в:

2C QD TC AD 6C 3D TD 3H 5H 7H AS JH KH 
3C 4C 2D AC QC 7S 7C TD 9C 4D KS 8D 6C 
2C 3C KC JC 4C 8C 7C QC AC 5C 9C 6C TC 
5H 3S 4D KC 9S 3D 4S 8H JC TC 8S 2S 4C 
2S 5D 6S 8S 9D 3C 2H TH 
2H 6D %S 8S 7S 4D 3H 4S KS QH JH 5C 9S 
2C QD TC AD 6C 3D TD 3C 5H 7H AS JH KD QS 
2C QD TC AD 6C 3D TD 2C 5D 7H AS JH KD 
2H 6D TS 8Z 7S 4D 3H 4S KS QD JH 5C 9S 

С каждой пары, представляющей собой карту (стоимость и костюм).

Правовые ценности включают в себя:

2-9 
T(10), A(Ace), K(King), Q(Queen), and J(Jack) 

и костюмы:

C(Clubs), S(Spades), D(Diamonds), and H(Hearts) 

После того, как файл считывается, каждая рука должна быть отсортированы сначала по масти, а затем рангом в масти (тузы высокие). Когда сортировка завершена, каждая рука должна быть оценена с помощью следующих правил:

Aces = 4 
Kings = 3 
Queens = 2 
Jacks = 1 
voids (no cards in a suit) = 3 
singletons (one card in a suit) = 2 
doubletons (two cards in a suit) = 1 
long suits (more than 5 cards in a suit) = 1 count for each card over 5 in number 

После оцениваемых, каждая рука должна отображаться в следующем формате:

Example Input: 
2C QD TC AD 6C 3D TD 3H 5H 7H AS JH KH 

Example Output: 
Clubs 10 6 2 
Diamonds A Q 10 3 
Hearts K J 7 5 3 
Spades A 
Points = 16 

Вот несколько особенностей о что программа должна включать:

1. A data structure to hold cards in an ordered manner. 
2. A function to read in the hand. 
3. A function to evaluate the hand (with support functions). 
4. A function to display the hand. 

Вот какой маленький код мне удалось придумать. В случае, если это неясно, комментарии - это шаги, которые, я думаю, нужно будет сделать, чтобы программа работала должным образом. Сейчас все, что он делает, это открыть файл, и да, я удалю сообщение «Файл открыт», я просто хотел убедиться, что файл действительно открыт.

//#include <program3.h> 
#include <iostream> 
#include <string> 
#include <fstream> 
using namespace std; 

int main() { 
    //Create Array 
    //char bridgeHands[]; 
    //Open file, if it doesn't exist, exit the program 
    ifstream bridgeFile; 
    bridgeFile.open("prog3.dat"); 
    if(!bridgeFile) { 
     cerr << "Open Failure" << endl; 
     exit(1); 
    } 
    else { 
     //Read file into array 
     //Sort array 
     //Evaluate hands 
     //Display hands 
     cout << "File is open" << endl; 
    } 

    return 0; 
} 

Я предполагаю, что мой конкретный вопрос на данный момент. Как мне нужно создавать и загружать массив? Я никогда не работал с загрузкой массива из ввода, который находится в парах. Кроме того, как это работает с структурой данных?

Я уверен, что теперь вы можете сказать, что я очень новичок в этом, и я учусь, когда я иду (почти все, что я знаю, как делать на C++ написано в этом коде), поэтому любая помощь в значительной степени оценили. Спасибо за ваше время.

+1

Вам нужна структура данных для представления карты (а структура будет отлично). Определите массив из них (используйте 'std :: vector', если вам разрешено).Напишите функцию перевода из двухсимвольной последовательности в тип карты. В цикле читайте двухзначные «слова», переводите каждый на карту и храните их в массиве. И не используйте 'eof'. – molbdnilo

+0

Звучит неплохо, но я не знаю, как это сделать: -/ –

+0

В этом случае вы найдете помощь [здесь] (http://stackoverflow.com/questions/388242/the-definitive-c -book-гид-и-лист). – TobiMcNamobi

ответ

2

В моем сознании много открытых вопросов. Сначала и прежде всего: каждая рука должна быть отдельной линией, или это только следующие 13 карт, независимо от разрывов строк. Это изменяет способ чтения рук.В любом случае ваш входной файл имеет ошибки , которые должны быть обнаружены: в первом случае пятая и седьмая строки имеют неправильный формат, а во втором случае количество карт не кратно 13, поэтому должна быть ошибка где-то.

Во всяком случае, правильный способ решения этой проблемы является определить типы (классов) для карт и рук, и определяется пользователь определяется operator>> для каждого, с operator>> для рук, используя один для карт. Например:

std::istream& operator>>(std::istream& source, Card& object) 
{ 
    char value; 
    char suit; 
    source >> std::ws; // skip leading whitespace. 
    source.get(value); // these do _not_ skip whitespace 
    source.get(suit); 
    if (source) {  // no errors on input... 
     // Map the characters to the internal representation and write 
     // them into `object`. This operator may have to be a friend 
     // to do this. 
     // 
     // If one of the characters isn't legal: 
     //  source.setstate(std::ios_base::failbit); 
    } 
    return source; 
} 

Для стороны, если ваш вход линии ориентированной, лучшее решение , вероятно, использовать std::getline прочитать строку, а затем std::istringstream разобрать его. Удостоверьтесь, что вы проверяете, что осталось только пустое место после того, как вы прочитали карты 13 . (Если вход игнорирует окончания строки, то достаточно читать 13 карт должно быть достаточно.) Независимо от стратегии, убедитесь, что проверка ошибок после каждого считывания перед использованием значений вы прочитали. Таким образом, вы петлю (либо на std::istringstream или первоначального источника, в зависимости) может выглядеть примерно так:

int i = 0; 
while (i != 13 && source >> dest[i]) { 
    ++ i; 
} 
if (i == 13) { 
    // Input of 13 cards succeeded... 
} 

Наконец: Вы ввода содержит ошибки (возможно, намеренно, , чтобы убедиться, что вы проверить их правильно). Это означает, что простейшая форма внешнего контура будет работать некорректно (так как остановится при первой ошибке). Если мы предположим, линию, ориентированную вход в глобальном масштабе, но >> оператор вручную игнорирует строки окончаний и просто ищет следующий 13 карты:

std::string line; 
int lineNumber = 0; 
while (std::getline(source, line)) { 
    ++ lineNumber; 
    std::istringstream parser(line); 
    if (parser >> hand >> std::ws && parser.get() == EOF) { 
     // Line is good, hand contains the instance to be evaluated 
    } else { 
     std::cerr << "Input format error in line " << lineNumber << std::endl; 
    } 
} 

Concering условие в if: мы читаем руку, затем пропустить пустое пространство; если это удастся, мы проверим, что мы достигли конца файла (в противном случае в конце строки есть лишний мусор). Вы можете дать более подробное сообщение об ошибке, если вы отделите эти разные операции, хотя, чтобы указать , какая карта является ошибкой, вам необходимо ввести 13 карт прямо на этот уровень, вместо того, чтобы использовать >> для Hand.

Еще одно предложение: я бы выбрал внутреннее представление , которое сделало обработку простой, с функциями отображения для ввода и вывода. Это, вероятно, две перечисления: одна для значений (с значениями в порядке их ранжирования), одна для костюмов (также в порядке их ранжирования). Это сделает сортировку и подсчет значительно проще, а функции отображения очень легки: для небольших наборов, подобных этим, не более чем массив с юридическими представлениями: на входе, линейном поиске и на выходе, просто индекс. (Обратите внимание, что это может привести к значению 2, имеющая числовое значение 0 внутренне, так как это будет первого значением перечисления.)

+0

Да, вы Правильно, я забыл упомянуть, что мы также должны включать проверку ошибок, поэтому наш профессор бросил несколько строк с некоторым недопустимым вводом (слишком много карт, слишком мало карточек и недопустимых костюмов или значений). –

+0

@BethTanner Что является хорошей идеей; ошибки ввода неизбежны в реальном мире, и реальные программы должны быть в состоянии справиться с ними. –

0

Используйте функцию ifstream::getline() для чтения и разбора файла. В этой ссылке вы также можете найти хороший пример того, как можно прочитать файл непосредственно в std::array:

#include <iostream> 
#include <sstream> 
#include <vector> 
#include <array> 

int main() 
{ 
    std::istringstream input("abc|def|gh"); 
    std::vector<std::array<char, 4>> v; 

    // note: the following loop terminates when std::ios_base::operator bool() 
    // on the stream returned from getline() returns false 
    for (std::array<char, 4> a; input.getline(&a[0], 4, '|');) { 
     v.push_back(a); 
    } 

    for (auto& a : v) { 
     std::cout << &a[0] << '\n'; 
    } 
} 

Но внимательно посмотрим, так ли это подходит для вашего случая. В качестве альтернативы вы можете опустить последний параметр getline, чтобы вы действительно получали строки по одному. Затем вам придется разбирать эти строки, используя std::string::find() и std::string::substr().

Смежные вопросы